Rails 3 NoMethod 错误 - Profiles#edit with CanCan 中配置文件的未定义方法
在我的 Rails 3 应用程序中,我在注册过程中被重定向到登录。注册步骤应该是:
- 用户创建用户和个人资料
- 保存用户后,用户将登录到应用程序并重定向到 Profiles#edit (
/signup/join
) - 保存个人资料后,用户将被重定向to Profiles#show (
/profiles/:id
)
在第 1 步之后,我被重定向到 /login
,并且在重定向后看到 302 错误。如果我在 profiles_controller.rb
中注释掉我的 before_filter :authenticate
并重做上述步骤,我不会被重定向出 /signup/join
但我收到以下错误:
NoMethodError in ProfilesController#edit
undefined method `profile' for nil:NilClass
我被指向我的 Profiles#edit
操作的第一行:
def edit
@profile = user.profile
if @profile.higher_ed?
higher_ed = HigherEd.find_or_create_by_name(:name => @profile.higher_ed)
end
if @profile.employer?
employer = Employer.find_or_create_by_name(:name => @profile.employer)
end
render :layout => "join_form"
end
我一直在尝试在我的应用程序中实现 CanCan,所以我认为这就是原因。但是,我注释掉了整个 ability.rb
文件,问题仍然存在。我显然想弄清楚如何在不注释掉 before_filter
的情况下解决这个问题。因此,如果有人有想法,我将不胜感激。 我将从 application_controller.rb
中 current_user
的定义开始:
protected
# Returns the currently logged in user or nil if there isn't one
def current_user
return unless session[:user_id]
@current_user ||= User.find_by_id(session[:user_id])
@current_user ||= User.find_by_auth_token!(cookies[:auth_token]) if cookies[:auth_token]
end
# Make current_user available in templates as a helper
helper_method :current_user
由于我正在处理依赖于 current_user
的 CanCan,因此 我的users_controller.rb:
class UsersController < ApplicationController
before_filter :authenticate, :only => [:edit, :update, :index]
layout "application"
def new
@user = User.new
@user.profile = Profile.new
if logged_in?
redirect_to current_user.profile
end
end
def create
@user = User.new(params[:user])
if @user.save
session[:user_id] = @user.id
redirect_to join_path, :notice => 'User successfully added.'
UserMailer.registration_confirmation(@user).deliver
else
render :action => 'new'
end
end
我的profiles_controller.rb:
class ProfilesController < ApplicationController
#before_filter :authenticate, :only => [:edit, :update]
helper_method :find_or_create_group
layout "application", :except => [:edit, :show]
def new
@profile = Profile.new(params[:profile])
end
def create
@profile = Profile.new(params[:profile])
if @profile.save
redirect_to @user.profile, :notice => 'User successfully added.'
else
render :new
end
if @profile.higher_ed?
HigherEd.find_or_create_by_name(:name => @profile.higher_ed)
end
if @profile.employer?
Employer.find_or_create_by_name(:name => @profile.employer)
end
if @profile.job_title?
JobTitle.find_or_create_by_name(:name => @profile.job_title)
end
if @profile.high_school?
HighSchool.find_or_create_by_name(:name => @profile.high_school)
end
end
def user
@user = current_user
end
def edit
@profile = user.profile
if @profile.higher_ed?
higher_ed = HigherEd.find_or_create_by_name(:name => @profile.higher_ed)
end
if @profile.employer?
employer = Employer.find_or_create_by_name(:name => @profile.employer)
end
render :layout => "join_form"
end
我的sessions_controller.rb:
class SessionsController < ApplicationController
def new
end
def create
if user = User.authenticate(params[:email].downcase, params[:password])
session[:user_id] = user.id
cookies.permanent[:auth_token] = user.auth_token
if user.profile.higher_ed?
redirect_to user.profile, :notice => "Logged in successfully"
else
redirect_to join_path, :notice => "Logged in successfully"
end
else
flash.now[:alert] = "Invalid login/password. Try again!"
render :action => 'new'
end
end
def destroy
reset_session
cookies.delete(:auth_token)
redirect_to root_path, :notice => "You successfully logged out"
end
end
我的CanCan 的 ability.rb
:
class Ability
include CanCan::Ability
def initialize(user)
user ||= User.new guest user
if user.role? :admin
can :manage, :all
else
can :manage, :all
end
end
end
我的 routes.rb
:
match "/signup/join" => "profiles#edit", :as => 'join'
In my Rails 3 app, I'm getting redirected to login during my signup process. The steps to signup are supposed to be:
- User creates User and Profile
- Upon saving user, user is logged into the app and redirected to Profiles#edit (
/signup/join
) - Upon saving profile, user is redirect to Profiles#show (
/profiles/:id
)
I'm getting redirected to /login
after step 1, and I'm seeing a 302 error after the redirect. If I comment out my before_filter :authenticate
in profiles_controller.rb
and redo the steps above I don't get redirected out of /signup/join
but I get the following error:
NoMethodError in ProfilesController#edit
undefined method `profile' for nil:NilClass
I'm pointed to the first line of my Profiles#edit
action:
def edit
@profile = user.profile
if @profile.higher_ed?
higher_ed = HigherEd.find_or_create_by_name(:name => @profile.higher_ed)
end
if @profile.employer?
employer = Employer.find_or_create_by_name(:name => @profile.employer)
end
render :layout => "join_form"
end
I've been making an attempt to implement CanCan in my app, so I thought that was the cause. However I commented out my entire ability.rb
file and the problem persists. I'd obviously like to figure out how to fix this without commenting out the before_filter
. So if anyone has an idea I'd greatly appreciate it. Since I'm dealing with CanCan which depends on a current_user
, I'll start with the definition of current_user
in my application_controller.rb
:
protected
# Returns the currently logged in user or nil if there isn't one
def current_user
return unless session[:user_id]
@current_user ||= User.find_by_id(session[:user_id])
@current_user ||= User.find_by_auth_token!(cookies[:auth_token]) if cookies[:auth_token]
end
# Make current_user available in templates as a helper
helper_method :current_user
Here's my users_controller.rb
:
class UsersController < ApplicationController
before_filter :authenticate, :only => [:edit, :update, :index]
layout "application"
def new
@user = User.new
@user.profile = Profile.new
if logged_in?
redirect_to current_user.profile
end
end
def create
@user = User.new(params[:user])
if @user.save
session[:user_id] = @user.id
redirect_to join_path, :notice => 'User successfully added.'
UserMailer.registration_confirmation(@user).deliver
else
render :action => 'new'
end
end
My profiles_controller.rb
:
class ProfilesController < ApplicationController
#before_filter :authenticate, :only => [:edit, :update]
helper_method :find_or_create_group
layout "application", :except => [:edit, :show]
def new
@profile = Profile.new(params[:profile])
end
def create
@profile = Profile.new(params[:profile])
if @profile.save
redirect_to @user.profile, :notice => 'User successfully added.'
else
render :new
end
if @profile.higher_ed?
HigherEd.find_or_create_by_name(:name => @profile.higher_ed)
end
if @profile.employer?
Employer.find_or_create_by_name(:name => @profile.employer)
end
if @profile.job_title?
JobTitle.find_or_create_by_name(:name => @profile.job_title)
end
if @profile.high_school?
HighSchool.find_or_create_by_name(:name => @profile.high_school)
end
end
def user
@user = current_user
end
def edit
@profile = user.profile
if @profile.higher_ed?
higher_ed = HigherEd.find_or_create_by_name(:name => @profile.higher_ed)
end
if @profile.employer?
employer = Employer.find_or_create_by_name(:name => @profile.employer)
end
render :layout => "join_form"
end
My sessions_controller.rb
:
class SessionsController < ApplicationController
def new
end
def create
if user = User.authenticate(params[:email].downcase, params[:password])
session[:user_id] = user.id
cookies.permanent[:auth_token] = user.auth_token
if user.profile.higher_ed?
redirect_to user.profile, :notice => "Logged in successfully"
else
redirect_to join_path, :notice => "Logged in successfully"
end
else
flash.now[:alert] = "Invalid login/password. Try again!"
render :action => 'new'
end
end
def destroy
reset_session
cookies.delete(:auth_token)
redirect_to root_path, :notice => "You successfully logged out"
end
end
My ability.rb
for CanCan:
class Ability
include CanCan::Ability
def initialize(user)
user ||= User.new guest user
if user.role? :admin
can :manage, :all
else
can :manage, :all
end
end
end
My routes.rb
:
match "/signup/join" => "profiles#edit", :as => 'join'
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
尝试将上面的行更改为
or
该问题与 cancan 无关,而是与控制器中的“user”为零有关。
Try changing the above line to
or
The issue has nothing to do with cancan, rather it has to do with "user" being nil in your controller.
我通过重新设计我的
current_user
逻辑来让它工作。现在是这样:这似乎已经成功了。
I got it working by reworking my
current_user
logic. It's now:That seems to have done the trick.