我跟着railscast #250 Authentication from 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
class User < ActiveRecord::Base
attr_accessible :email, :password, :password_confirmation#, :admin
validates :email, :uniqueness => true
has_secure_password
end
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
<% 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 %>
答案 0 :(得分:13)
current_user
将为nil。所以你需要这样做:
<% if current_user && current_user.admin? %>
或使用try
方法Rails添加到所有对象。
<% if current_user.try(:admin?) %>
答案 1 :(得分:3)
正如Dogbert所说,如果用户没有登录,current_user
将为零。
我建议另外两种选择:
current_user
方法中的 1)返回特殊类型“guest”用户而不是nil。如果您希望稍后使用其他内容,例如响应某些用户操作,则Il将非常有用
作为灵感,请看看Ryan Bates如何解释他的宝石 cancan的Ability
类:link。
他所做的第一件事就是创建一个统一的(而不是持久的DB)用户。每次Rails使用这种用户验证解析ERB模板时,都会实例化Ability
类。
所以,你可以这样做:
def current_user
@current_user ||= ((User.find(session[:user_id]) if session[:user_id]) || User.new)
end
因此,如果(User.find(session[:user_id]) if session[:user_id])
返回nil
,则@current_user
将设置为未初始化的用户,在DB中没有身份。
2)定义一个新的metod只是为了检查用户是否是管理员,例如:
# 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
这样你就可以这样使用它了:
<% if is_an_admin? %>
<div>
<%= do stuff....%>
...这可能是一个额外的方法调用,但它也可能使您的代码更具可读性。
答案 2 :(得分:1)
我知道这是旧的,但如果有人像我一样搜索错误,Rails教程中实际上没有错误,但他们忘了强调他们添加的一件事。
KCSTDLIB_API_FUNC(size_t DECL_CALL strspn(const char * str1, const char * str2))
{
size_t count = 0;
auto isin = [&](char c)
{
for (size_t x = 0; str2[x]; x++)
{
if (c == str2[x])
return true;
};
return false;
};
for (; isin(str1[count]); count++);
return count;
}
请注意,他们在此添加了:destroy action,之前没有添加,这确保用户被记录以执行销毁操作,然后检查他是否是管理员
before_action :logged_in_user, only: [:index, :edit, :update, :destroy]
截至2015年12月14日编辑时,rails教程现在添加了代码清单9.53中的:destroy操作。如果你像我一样错过了那个,你就会收到这个错误。
答案 3 :(得分:-3)
在您的用户模型中看起来像:
attr_accessible :email, :password, :password_confirmation#, :admin
admin已注释掉,您需要删除#。