【问题标题】:Rails 4: NoMethodError in <Model>Controller#indexRails 4:<Model>Controller#index 中的 NoMethodError
【发布时间】:2015-07-10 02:57:19
【问题描述】:

在我们的 Rails 4 应用程序中,有四种模型:

class User < ActiveRecord::Base
  has_many :administrations, dependent: :destroy
  has_many :calendars, through: :administrations
end

class Administration < ActiveRecord::Base
  belongs_to :user
  belongs_to :calendar
end

class Calendar < ActiveRecord::Base
  has_many :administrations, dependent: :destroy
  has_many :users, through: :administrations
end

这是我们的AdministrationsController

class AdministrationsController < ApplicationController

  def to_s
    role
  end

  def index
    @user = current_user
    @administrations = @user.administrations
    @calendar = Calendar.new
  end

  def show
    @administration = Administration.find(params[:id])
  end

  def destroy
    Administration.find(params[:id]).destroy
    flash[:success] = "You successfully quit this calendar"
    redirect_to dashboard_path
  end

end

当一个新的user注册时,即:一个新的@user被创建,他被重定向到他的dashboard,对应Administrationindex.html.erb视图:

<% provide(:title, 'Dashboard') %>

<h1>Dashboard</h1>

<div class="container-fluid">

    <div class="row">

        <div class="col-md-4 col-md-offset-4">
            <% if @user.administrations.any? %>
                <h2>My Calendars</h2>
                <table>
                    <%= render @administrations %>
                </table>
            <% end %>

            <section class="calendar_form">
                <%= render 'shared/calendar_form' %>
            </section>
        </div>

    </div>

</div>

此时,用户没有日历,也没有管理权限。

所以,从逻辑上讲,在我们注册一个新用户后,我们会收到以下错误:

NoMethodError in AdministrationsController#index

undefined method `administrations' for nil:NilClass

def index
  @user = current_user
  @administrations = @user.administrations
  @calendar = Calendar.new
end

我们试图做类似的事情:

def index
  @user = current_user
  @administrations = @user.administrations if @user.administrations.exists?
  @calendar = Calendar.new
end

但它不起作用,并返回了类似的错误。

我们如何解决这个问题?

【问题讨论】:

    标签: ruby-on-rails ruby-on-rails-4 model-view-controller nomethoderror


    【解决方案1】:

    问题在于current_user 返回的是nil,而不是用户对象。也许你已经创建了一个用户但没有登录。

    【讨论】:

    • 你是对的:因为,我们有一个包括电子邮件验证系统在内的身份验证系统,并且我们要求用户在登录仪表板之前实际激活他们的帐户,然后,当我们注册一个新用户并将他重定向到他的仪表板,我们得到错误。我们是否应该重定向到主页,以防止发生此问题?
    • 当然——你可以在应用程序助手中创建一个login_required方法,如果current_user为nil,它会重定向到一个希望页面,并将before_filter :login_required放在任何需要登录用户的控制器的顶部
    • 会的。非常感谢。实际上,我们已经实现了类似的东西,在我们的sessions helper 中有一个def log_in(user) session[:user_id] = user.id end。但是,我读到这不是 Rails 的最佳实践。您的解决方案会是更好、更安全的选择吗?
    • 看起来您正在尝试在注册后自动登录用户 - 这是描述该过程的帖子:stackoverflow.com/questions/5916818/… - 在此帖子中 do_login 相当于您的 @ 987654330@函数。
    • 我同意您可能不应该直接编写会话变量,而应该依赖为用户身份验证构建的实用方法;例如,如果您使用的是 Devise gem,它会提供像 authenticate_user!sign_in(@user) 这样的方法。这是一篇关于使用 Devise 的好文章:gotealeaf.com/blog/…
    【解决方案2】:

    您可以使用#respond_to? 方法

    @administrations = @user.administrations if @user.respond_to? :admininstrations

    【讨论】:

    • 我们尝试了此解决方案和您建议的上一个解决方案(使用#try),它似乎解决了问题,同时导致了一个新错误:NoMethodError in AdministrationsController#index undefined method 'administrations' for nil:NilClassAdministration index.html.erb 视图文件中的 &lt;% if @user.administrations.any? %&gt; 可能是此错误的根本原因,我现在将其添加到问题中。
    • 你应该可以在那里使用try。看着你的模型,@user 总是回应管理,不是吗?
    • 是的,你是对的。正如@FredWillmore 所指出的,问题似乎来自于我们创建了一个用户但没有让他登录的事实。非常感谢您的帮助。
    猜你喜欢
    • 2013-03-27
    • 1970-01-01
    • 1970-01-01
    • 2015-07-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-09
    • 2014-02-07
    相关资源
    最近更新 更多