Rails 3 NoMethod 错误 - Profiles#edit with CanCan 中配置文件的未定义方法

发布于 2025-01-05 05:29:13 字数 4678 浏览 0 评论 0原文

在我的 Rails 3 应用程序中,我在注册过程中被重定向到登录。注册步骤应该是:

  1. 用户创建用户和个人资料
  2. 保存用户后,用户将登录到应用程序并重定向到 Profiles#edit (/signup/join)
  3. 保存个人资料后,用户将被重定向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.rbcurrent_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:

  1. User creates User and Profile
  2. Upon saving user, user is logged into the app and redirected to Profiles#edit (/signup/join)
  3. 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

欲拥i 2025-01-12 05:29:13
@profile = user.profile

尝试将上面的行更改为

@profile = @current_user.profile

or

@profile = current_user.profile

该问题与 cancan 无关,而是与控制器中的“user”为零有关。

@profile = user.profile

Try changing the above line to

@profile = @current_user.profile

or

@profile = current_user.profile

The issue has nothing to do with cancan, rather it has to do with "user" being nil in your controller.

你不是我要的菜∠ 2025-01-12 05:29:13

我通过重新设计我的 current_user 逻辑来让它工作。现在是这样:

def current_user
  @current_user ||= lookup_user
end

def lookup_user
  if cookies[:auth_token]
    User.find_by_auth_token!(cookies[:auth_token])
  elsif session[:user_id]
    User.find_by_id(session[:user_id])
  end
end

这似乎已经成功了。

I got it working by reworking my current_user logic. It's now:

def current_user
  @current_user ||= lookup_user
end

def lookup_user
  if cookies[:auth_token]
    User.find_by_auth_token!(cookies[:auth_token])
  elsif session[:user_id]
    User.find_by_id(session[:user_id])
  end
end

That seems to have done the trick.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文