2013-07-17 82 views
1

我有一个轨道4的应用程序,以崭新的PG数据库中运行,经过20个用户创建我开始收到此错误未定义的方法`gravatar_url”的零:NilClass

ActionView::Template::Error (undefined method `gravatar_url' for nil:NilClass): 

这里是用户。 RB型号:

 def gravatar_url 
     stripped_email = email.strip 
     downcased_email= stripped_email.downcase 
     hash = Digest::MD5.hexdigest(downcased_email) 

     "http://gravatar.com/avatar/#{hash}?r=x" 
     end 

这里是index.html.erb

<% @statuses.each do |status| %> 
<div class="status"> 
    <div class ="row"> 
    <div class="span1"> 
     <%= image_tag status.user.gravatar_url %> 
    </div> 
    <div class="span7"> 
     <strong><%= status.user.full_name %></strong> 
     <p><%= status.content %></p> 
     <div class="meta"> 
     <%= link_to time_ago_in_words(status.created_at) + " ago" , status %> 
     <span class="admin"> 
      | <%= link_to "Edit", edit_status_path(status) %> | 
      <%= link_to "Delete", status, method: :delete, data: { confirm: "Are      you sure you want to delete this status?"} %> 
     </span> 
     </div> 
    </div> 
    </div> 
</div> 

如果我用耙滴数据库,并从头开始DB:迁移它工作得很好,但一旦我打了20个用户,事情开始变坏,应用程序会抛出异常。

这里的状态控制器

class StatusesController < ApplicationController 
    before_action :set_status, only: [:show, :edit, :update, :destroy] 

    before_filter :authenticate_user!, only: [:new, :create, :edit, :update] 


    # GET /statuses 
    # GET /statuses.json 
    def index 
    @statuses = Status.all 
    end 

    # GET /statuses/1 
    # GET /statuses/1.json 
    def show 
    end 

    # GET /statuses/new 
    def new 
    @status = Status.new 
    end 

    # GET /statuses/1/edit 
    def edit 
    end 

    # POST /statuses 
    # POST /statuses.json 
    def create 
    @status = current_user.statuses.new(status_params) 

    respond_to do |format| 
     if @status.save 
     format.html { redirect_to @status, notice: 'Status was successfully created.' } 
     format.json { render action: 'show', status: :created, location: @status } 
     else 
     format.html { render action: 'new' } 
     format.json { render json: @status.errors, status: :unprocessable_entity } 
     end 
    end 
    end 

    # PATCH/PUT /statuses/1 
    # PATCH/PUT /statuses/1.json 
    def update 
    @status = current_user.statuses.find(params[:id]) 

    if params[:status] && params[:status].has_key?(:user_id) 
     params[:status].delete(:user_id) 
    end 


    respond_to do |format| 
     if @status.update(status_params) 
     format.html { redirect_to @status, notice: 'Status was successfully updated.' } 
     format.json { head :no_content } 
     else 
     format.html { render action: 'edit' } 
     format.json { render json: @status.errors, status: :unprocessable_entity } 
     end 
    end 
    end 

    # DELETE /statuses/1 
    # DELETE /statuses/1.json 
    def destroy 
    @status.destroy 
    respond_to do |format| 
     format.html { redirect_to statuses_url } 
     format.json { head :no_content } 
    end 
    end 

    private 
    # Use callbacks to share common setup or constraints between actions. 
    def set_status 
     @status = Status.find(params[:id]) 
    end 

    # Never trust parameters from the scary internet, only allow the white list through. 
    def status_params 
     params.require(:status).permit(:name, :content, :user_id) 
    end 
end 

下面是状态类:

class Status < ActiveRecord::Base 
    belongs_to :user 

    validates :content, presence: true, 
         length:{ minimum: 2 } 

    validates :user_id, presence: true 

end 

这里是用户等级:

class User < ActiveRecord::Base 
    # Include default devise modules. Others available are: 
    # :token_authenticatable, :confirmable, 
    # :lockable, :timeoutable and :omniauthable 
    devise :database_authenticatable, :registerable, 
     :recoverable, :rememberable, :trackable, :validatable 

    validates :first_name, presence: true 

    validates :last_name, presence: true 

    validates :profile_name, presence: true, 
          uniqueness: true, 
          format: { 
          with: /\A[a-zA-Z0-9_-]+\Z/, 
          message: 'must be formatted correctly.' 
          } 

    has_many :statuses 
end 

和应用程序控制器:

class ApplicationController < ActionController::Base 
    before_filter :configure_permitted_parameters, if: :devise_controller? 

    protect_from_forgery with: :exception 

    protected 

    def configure_permitted_parameters 
    devise_parameter_sanitizer.for(:sign_up) { |u| u.permit(:first_name, :last_name, :profile_name, 
                  :email, :password, :password_confirmation) } 

    devise_parameter_sanitizer.for(:statuses) { |u| u.permit(:user_id)} 
    end 
end 
+0

可以:

有条件地破坏了has_one孩子被破坏的情况下家长,您可以将子模型(User)将执行当用户被破坏内实施一系列回调你显示控制器? –

+0

以及用户和状态类。你看,用户不存在导致问题。 –

+0

@HélioSantos我添加了请求的类/控制器 – VanDanny

回答

0

至少一个不与一个用户相关联。您的观点是抛出一个错误,因为它最终试图访问status.usergravatarl_url方便的方法,但因为状态没有用户,它抛出一个异常ActionView::Template::Error (undefined method 'gravatar_url' for nil:NilClass):

试想以下情形:

Status.find(1).user.nil? == false 
Status.find(2).user.nil? == false 
Status.find(3).user.nil? == true # no associated user 
Status.find(4).user.nil? == false 

当您指定Status.all@statuses实例变量,它会包括所有四种状态 - 包括第三状态,其中有没有相关的用户。当在你看来遍历@statuses,您会收到一个错误,当第三状态循环:

# first pass 
status.user # found 

# second pass 
status.user # found 

# third pass 
status.user # NilClass exception is thrown, causing loop to exit 

要确定哪些状态没有相关的用户,运行以下阿雷尔查询:

Status.joins("left join users on users.status_id = statuses.id").where("users.status_id is null") 
#=> [#<Status id: 3>] 

要解决此错误,只是用户与没有用户的状态相关联:

status = Status.find(3) 
user = User.create 
status.user = user # associates `user` with `status` 

Status.joins("left join users on users.status_id = statuses.id").where("users.status_id is null") 
#=> [] # all statuses are now associated with a user 

UPDATE

# app/models/user.rb 
class User < ActiveRecord::Base 
    # ... existing logic 

    before_destroy :find_parent 
    after_destroy :destroy_orphaned_parent 

    def find_parent 
     @parent = self.parent 
    end 

    def destroy_orphaned_parent 
     if @parent.children.length == 0 
      @parent.destroy 
     end 
    end 
end 
+0

状态没有用户,因为我留下了一个删除选项,没有删除新删除的用户的状态。谢谢你,先生。这20个用户是任意的,并且与这个bug无关。我会在明天回答我的最终答案。 – VanDanny

+0

请参阅我的更新答案,以解决关联用户销毁时会自动销毁状态的解决方案。 – zeantsoi

+0

更新有什么好运? – zeantsoi

0

问题是status.user返回nil,这意味着没有user_id属性是nil(或NULL,在数据库中)。

另一个选项可为用户不再存在,但我相信,如果你想看看它会抛出一个错误。经由Status.all检索到的状态的

+0

那么在20个用户之后会发生什么情况会导致运行中的应用程序进入非运行状态?为什么零现在? – VanDanny

相关问题