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

时间:2012-02-15 04:49:27

标签: ruby-on-rails-3 cancan

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

  1. 用户创建用户和个人资料
  2. 保存用户后,用户登录应用并重定向到个人资料#edit(/signup/join
  3. 保存个人资料后,用户将重定向到个人资料#show(/profiles/:id
  4. 我在第1步之后被重定向到/login,我在重定向后看到302错误。如果我在before_filter :authenticate中注释掉profiles_controller.rb并重做上述步骤,则不会重定向到/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的情况下弄清楚如何解决这个问题。所以,如果有人有想法,我会非常感激。由于我正在处理依赖于current_user的CanCan,因此我将从current_userapplication_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
    

    这是我的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'
    

2 个答案:

答案 0 :(得分:3)

@profile = user.profile

尝试将上述行更改为

@profile = @current_user.profile

@profile = current_user.profile

这个问题与cancan无关,而是与你的控制器中的“user”nil有关。

答案 1 :(得分:0)

我通过重新修改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

这似乎已经成功了。