I have a rails app with a Project
model and a nested Pictures
model. Im using the Paperclip gem to upload images to the pictures
model, and nested_form gem to nest the Picture
model within the projects
. Everything was working perfectly, the images were showing and the code seemed to be working fine, until suddenly after working on another part of the app, I started getting the error mentioned in the question title. Specifically, this line in my index page seems to be the issue: <%= link_to image_tag(project.pictures.first.image.url(:thumb)), project %>
I cant seem to figure out the problem as it was working fine before. I even reverted back to a previous commit when it was working, and im still getting the same error. Im totally stumped. Any help would be highly appreciated!
Index:
<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>
Projects model:
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
Pictures model:
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
Projects controller:
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
Pictures controller:
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
Most certainly, one of your projects
has no pictures.
When you call project.pictures.first.image.url(:thumb)
for each of your projects, you are getting all of its pictures, then the first one of those, and then the image for that first picture.
If your project has no pictures, then project.pictures
is an empty set. When you call .first
on an empty set, the result is nil. nil
is an object, of class NilClass
, and it has no method named image
. Ensure that each one of your projects has at least one image and you will not see the error. Alternatively you can create an if statement around your link_to
, so that you only evaluate that line if !project.pictures.empty?
.