Rails + Paperclip - NoMethodError в Projects#index - неопределенный метод `image' для nil:NilClass

У меня есть приложение rails с моделью Project и вложенной моделью Pictures. Я использую гем Paperclip для загрузки изображений в модель pictures, а гем nested_form — для вложения модели Picture в модель projects. Все работало отлично, изображения показывались, и код, казалось, работал нормально, пока внезапно после работы над другой частью приложения я не начал получать сообщение об ошибке, упомянутое в заголовке вопроса. В частности, эта строка на моей индексной странице кажется проблемой: <%= link_to image_tag(project.pictures.first.image.url(:thumb)), project %> Кажется, я не могу понять проблему, поскольку раньше она работала нормально. Я даже вернулся к предыдущей фиксации, когда она работала, и я все еще получаю ту же ошибку. Я полностью озадачен. Любая помощь будет высоко оценен!

Индекс:

<div id="pictures">
  <% @projects.each do |project| %>

  <div class="col-md-4">

    <div class="box panel panel-default">
      <div class="panel-heading">
        <h3 class="panel-title"><%= project.title %></h3>
      </div>
      <div class="image">
         <%= link_to image_tag(project.pictures.first.image.url(:thumb)), project %>
      </div>
      <div class="panel-body">

        <p>
          <strong>Progress:</strong>
          <%= progress_bar 0.6, label: true, alternative: 'info', striped: true %>
        </p>


        <p>
          <strong>Status:</strong>
          <%= project.status %>
        </p>


        <p>
          <strong>Phase:</strong>
          <%= project.phase %>
        </p>


        <%= link_to 'Show', project %> |
        <%= link_to 'Edit', edit_project_path(project) %> |
        <%= link_to 'Destroy', project, method: :delete, data: { confirm: 'Are you sure?' } %>
      </div>
    </div>
      </div>


  <% end %>
</div>

Модель проектов:

class Project < ActiveRecord::Base

  has_many :pictures, :dependent => :destroy
  has_many :teams, :dependent => :destroy

    accepts_nested_attributes_for :pictures, :reject_if => lambda { |a| a[:image].blank? }, allow_destroy: true
    accepts_nested_attributes_for :teams, :reject_if => lambda { |a| a[:member].blank? }, allow_destroy: true

end

Модель фотографий:

class Picture < ActiveRecord::Base

 belongs_to :project

 has_attached_file :image,
 path: ":rails_root/public/system/:attachment/:id/:style/:filename",
 url: "/system/:attachment/:id/:style/:filename",
:styles => { :medium => "900x900>", :thumb => "300x300>" }

 validates_attachment_content_type :image, :content_type => /\Aimage\/.*\Z/

end

Контролер проектов:

class ProjectsController < ApplicationController
  before_action :set_project, only: [:show, :edit, :update, :destroy]

  respond_to :html

  def index
    @projects = Project.all
    respond_with(@projects)
  end

  def show
    respond_with(@project)
  end

  def new
    @project = Project.new
    @project.pictures.build
    @project.teams.build
    respond_with(@project)
  end


  def edit
  end

  def create

    @project = Project.new(project_params)
    if @project.save
    flash[:notice] = "Successfully created project."
    redirect_to @project
    else
    render :action => 'new'
    end

  end

  def update
    @project.update(project_params)
    respond_with(@project)
  end

  def destroy
    @project.destroy
    respond_with(@project)
  end

  private
    def set_project
      @project = Project.find(params[:id])
    end

    def project_params
      params.require(:project).permit(:id, :title, :description, :status, :phase, :location, :contractor, :designer, :area, :budget, :project_start, :construction_period, :expected_date, :picture_id, :image, pictures_attributes: [:id, :image, :_destroy], teams_attributes: [:project_id, :user_id, :id, :member, :role, :_destroy])
    end
end

Контроллер изображений:

class PicturesController < ApplicationController
  before_action :set_picture, only: [:show, :edit, :update, :destroy]

  respond_to :html

  def index
    @pictures = Picture.all
    respond_with(@pictures)
  end

  def show
    respond_with(@picture)
  end

  def new
    @picture = Picture.new
    respond_with(@picture)
  end

  def edit
  end

  def create
    @picture = Picture.new(picture_params)
    @picture.save
    respond_with(@picture)
  end

  def update
    @picture.update(picture_params)
    respond_with(@picture)
  end

  def destroy
    @picture.destroy
    respond_with(@picture)
  end

  private
    def set_picture
      @picture = Picture.find(params[:id])
    end

    def picture_params
      params.require(:picture).permit(:image, :id, :project_id)
    end
end

person Rashed Al-Julaibi    schedule 16.08.2015    source источник


Ответы (1)


Наверняка у одного из ваших projects нет фотографий.

Когда вы вызываете project.pictures.first.image.url(:thumb) для каждого из ваших проектов, вы получаете все его изображения, затем первое из них, а затем изображение для этого первого изображения.

Если в вашем проекте нет картинок, то project.pictures — это пустой набор. Когда вы вызываете .first для пустого набора, результат нулевой. nil — это объект класса NilClass, и у него нет метода с именем image. Убедитесь, что в каждом из ваших проектов есть хотя бы одно изображение, и вы не увидите ошибку. В качестве альтернативы вы можете создать оператор if вокруг вашего link_to, чтобы вы оценивали только эту строку if !project.pictures.empty?.

person sealocal    schedule 16.08.2015
comment
Это действительно была проблема, и ваше предложение решило проблему. Большое спасибо! - person Rashed Al-Julaibi; 16.08.2015