Ruby on rails UsersController中的NoMethodError#更新用户属性后显示

Ruby on rails UsersController中的NoMethodError#更新用户属性后显示,ruby-on-rails,railstutorial.org,nomethoderror,Ruby On Rails,Railstutorial.org,Nomethoderror,我正在使用railstutorial.org的书籍。 我试着更新书中第7章所写的用户属性,但是电子邮件变成了零。我尝试过更新,但没有用。这会在UsersController#show:undefined方法'downcase'中为nil:NilClass生成一个NoMethodError 这是show.html.erb <% provide(:title, @user.name) %> <h1> <%= gravatar_for @user %> &l

我正在使用railstutorial.org的书籍。 我试着更新书中第7章所写的用户属性,但是电子邮件变成了零。我尝试过更新,但没有用。这会在UsersController#show:undefined方法'downcase'中为nil:NilClass生成一个NoMethodError

这是show.html.erb

<% provide(:title, @user.name) %>
<h1>
  <%= gravatar_for @user %>
  <%= @user.name %>
</h1>
用户控制器

class UsersController < ApplicationController
  def new
  end

  def show
    @user = User.find(params[:id])
  end
end
class UsersController
用户模型

class User < ActiveRecord::Base
  before_save { email.downcase! }
  validates :name, presence: true, length: { maximum: 50 }
  VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-]+(\.[a-z\d\-]+)*\.[a-z]+\z/i
  validates :email, presence: true,
                    format: { with: VALID_EMAIL_REGEX },
                    uniqueness: { case_sensitive: false }
  has_secure_password
  validates :password, presence: true, length: { minimum: 6 }
end
class用户

求你了,我需要帮助来解决这个问题。谢谢。

我也在学习本教程,所以我不会假装是Rails专家

也就是说,我只是回顾了围绕第一个介绍

before_save { email.downcase! }
语法,我在第6章的末尾看到了这一点

我很确定这对您不起作用,因为您的UsersController缺少“New”方法的定义:

我打赌你的@user对象是Nil,因为你还没有创建它的实例。顺便说一句,在本教程的这一点上,您还应该在UsersController中定义一个Create方法

编辑:如果您的问题仅限于Rails控制台中发生的事情,我同意您的意见,即您需要提供控制台会话的完整记录,以便大家提供完整的答案

以下是我的Rails教程项目中的Rails控制台会话示例:

  • 调用控制台并使其了解我的用户模型:

    $rails console  
    Loading development environment (Rails 4.2.2)  
    require './app/models/user'  
    => true  
    
  • 创建名为“spong”的用户实例

  • 请注意,我的初始电子邮件地址大小写不一

  • 调用downcase方法:

    spong.email.downcase 
    => "yodawg@dawg.com"  
    
  • 这在控制台中对我有效。现在,让我们尝试更新属性方法:

        spong.update_attributes(name: "The Dude", email: "dude@AbideS.org")
    
    这是直截了当的,但对我来说不起作用,因为在我的旅程中,我已经实现了防止此类更新的功能:

        (6.5ms)  begin transaction  
        User Exists (0.5ms)  SELECT  1 AS one FROM "users" WHERE LOWER("users"."email") = LOWER('dude@AbideS.org') LIMIT 1  
        User Exists (0.2ms)  SELECT  1 AS one FROM "users" WHERE LOWER("users"."email") = LOWER('dude@AbideS.org') LIMIT 1  
        (0.1ms)  rollback transaction  
        => false  
    
    正如哈特尔所说:

    请注意,如果任何验证失败,例如当保存记录需要密码时(如第6.3节所述),则更新_属性的调用将失败

  • 让我试试这个命令的单一版本:

    spong.update_attribute( :email, "dude@AbideS.org")  
    (3.7ms)  begin transaction  
    SQL (4.0ms) INSERT INTO "users" ("name", "email", "created_at", "updated_at", "activation_digest") VALUES (?, ?, ?, ?, ?)  [["name", "The Dude"], ["email", "dude@abides.org"], ... ]  
    (1.2ms)  commit transaction  
    ==> true  
    spong.email 
    => "dude@abides.org"
    
  • 这并不是说电子邮件地址在INSERT命令中已经转换成小写,这与预期完全一致,这要归功于此

    before_save { email.downcase! }
    
    我们在我们的用户模型中有

    但是所有的数据库活动是怎么回事?这是因为update_attributes更新单个属性,并且保存记录,而无需经过正常的验证过程(这就是为什么我能够这样做的原因)。在研究这一点时,我发现了关于update_属性和update_属性的信息。好东西

    好的,那么当(现有)电子邮件地址为空时,如果我们尝试调用update_属性会发生什么呢?让我们看看:

        newUser = User.new  
        => #<User id: nil, name: nil, email: nil, created_at: nil, updated_at: nil, password_digest: nil, remember_digest: nil, admin: nil, activation_digest: nil, activated: false, activated_at: nil>
    
    同样,由于update_attribute/update_attributes的行为,我的数据库被更新;与直觉相反,在这个“更新”过程中插入了一条记录,但这是因为我还没有将这条(或第一条)记录保存到数据库中


    我希望所有这些都能有所帮助。至少,我已经通过控制台证明了这一点——即使是以前的“nil”值(我在做尝试回答的研究时学到了很多)。

    你的
    @user
    变量是
    nil
    或者它的
    email
    列包含
    nil
    值。我认为这是由用户助手造成的。我现在创建了一个新用户,电子邮件被自动设置为零。我删除了helper并更新了第二个用户属性,它成功了。为什么会出现这种情况?@Emu该电子邮件会显示在rails控制台中,但不会显示在显示页面上记录是否已被保留(即,您是否在设置了
    email
    属性后保存了该记录)?
    user。email
    肯定为零。现在你只需要找出原因。是的,你是对的。这应该是解决的办法,在你发帖之前就解决了。无论如何,谢谢你;)请将此标记为已回答,以使我因所有的辛勤工作而获得一些声誉。:)谢谢
        (6.5ms)  begin transaction  
        User Exists (0.5ms)  SELECT  1 AS one FROM "users" WHERE LOWER("users"."email") = LOWER('dude@AbideS.org') LIMIT 1  
        User Exists (0.2ms)  SELECT  1 AS one FROM "users" WHERE LOWER("users"."email") = LOWER('dude@AbideS.org') LIMIT 1  
        (0.1ms)  rollback transaction  
        => false  
    
    spong.update_attribute( :email, "dude@AbideS.org")  
    (3.7ms)  begin transaction  
    SQL (4.0ms) INSERT INTO "users" ("name", "email", "created_at", "updated_at", "activation_digest") VALUES (?, ?, ?, ?, ?)  [["name", "The Dude"], ["email", "dude@abides.org"], ... ]  
    (1.2ms)  commit transaction  
    ==> true  
    spong.email 
    => "dude@abides.org"
    
    before_save { email.downcase! }
    
        newUser = User.new  
        => #<User id: nil, name: nil, email: nil, created_at: nil, updated_at: nil, password_digest: nil, remember_digest: nil, admin: nil, activation_digest: nil, activated: false, activated_at: nil>
    
        newUser.update_attribute(:email, "cOnFuSed@MixecCase.com")**  
        (1.2ms)  begin transaction  
        SQL (3.9ms)  INSERT INTO "users" ("email", "created_at", "updated_at", "activation_digest") VALUES (?, ?, ?, ?)  [["email", "confused@mixeccase.com"], ...]  
        (0.9ms)  commit transaction  
        => true