Hol*_*lly 5 authentication authorization ruby-on-rails railscasts ruby-on-rails-3
我跟着railscast#250来自Scratch的身份验证并且工作得很好.现在我只想在我的索引页面上显示编辑和销毁链接给管理员用户.
我已经设置了mu用户数据库,其中包含一个admin boolean字段,并尝试在另一个模型(hikingtrails)的视图中放置一个简单的if语句,只显示管理员用户的某些链接,但是当我尝试时,我收到此错误, undefined method 'admin?' for nil:NilClass
create_table "users", :force => true do |t|
t.string "email"
t.string "password_digest"
t.boolean "admin"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
Run Code Online (Sandbox Code Playgroud)
class User < ActiveRecord::Base
attr_accessible :email, :password, :password_confirmation#, :admin
validates :email, :uniqueness => true
has_secure_password
end
Run Code Online (Sandbox Code Playgroud)
class ApplicationController < ActionController::Base
protect_from_forgery
# fetch the currently logged-in user record to see if the user is currently logged in
# putting this method in ApplicationController so that it’s available in all controllers
private
def current_user
# checks for a User based on the session’s user id that was stored when they logged in, and stores result in an instance variable
@current_user ||= User.find(session[:user_id]) if session[:user_id]
end
# to give access to this method from all the views, the helper_method makes it a helper method
helper_method :current_user
# basic authorization, user must be logged in!
def authorize
redirect_to login_url, alert: "You must be logged in to perform this action" if current_user.nil?
end
end
Run Code Online (Sandbox Code Playgroud)
<% if current_user.admin? %>
<%= link_to t('.edit', :default => t("helpers.links.edit")),
edit_hikingtrail_path(hikingtrail), :class => 'btn btn-mini' %>
<%= link_to t('.destroy', :default => t("helpers.links.destroy")),
hikingtrail_path(hikingtrail),
:method => :delete,
:data => { :confirm => t('.confirm', :default => t("helpers.links.confirm", :default => 'Are you sure?')) },
:class => 'btn btn-mini btn-danger' %>
<% end %>
Run Code Online (Sandbox Code Playgroud)
Dog*_*ert 16
current_user如果用户未根据您的代码登录,则为nil.所以你需要这样做:
<% if current_user && current_user.admin? %>
Run Code Online (Sandbox Code Playgroud)
或使用tryRails方法添加到所有对象.
<% if current_user.try(:admin?) %>
Run Code Online (Sandbox Code Playgroud)
正如 Dogbert 所说,current_user如果用户未登录,它将为零。
我建议另外两种选择:
1)在current_user方法中返回一个特殊类型的“guest”用户而不是 nil。如果您想稍后用它做其他事情,例如响应某些用户操作,Il 将很有用。
作为灵感,看看瑞安贝茨如何解释Ability他的宝石康康舞类:链接。他做的第一件事是创建一个单元化(而不是持久化在 DB 中)用户。一个是AbilityJava类初始化每次Rails会解析ERB模板与类型的用户验证。
所以,你可以这样做:
def current_user
@current_user ||= ((User.find(session[:user_id]) if session[:user_id]) || User.new)
end
Run Code Online (Sandbox Code Playgroud)
因此,如果(User.find(session[:user_id]) if session[:user_id])返回nil,@current_user将被设置为未初始化的用户,在数据库中没有身份。
2)定义一个新的方法只是为了检查用户是否是管理员,例如:
# your unmodified current_user implementation
def current_user
@current_user ||= User.find(session[:user_id]) if session[:user_id]
end
def is_an_admin?
if current_user && current_user.admin?
end
Run Code Online (Sandbox Code Playgroud)
这样你就可以这样使用它:
<% if is_an_admin? %>
<div>
<%= do stuff....%>
Run Code Online (Sandbox Code Playgroud)
...它可能是一个额外的方法调用,但它也可能使您的代码更具可读性。
| 归档时间: |
|
| 查看次数: |
9515 次 |
| 最近记录: |