Deleting images with paperclip - ruby-on-rails

I'm trying to delete each single image uploaded for a model (work has many images) but now my code works like this: I have three images uploaded in a work, I want to delete just one but when I check the image's checkbox and submit the update action it will delete all the three images.
Here is my work model's code:
before_save :destroy_image?
belongs_to :category
has_many :images, :as => :assetable, :class_name => "Work::Image", :dependent => :destroy
accepts_nested_attributes_for :images, :reject_if => proc { |attributes| attributes['attachment'].blank? }
def image_delete
#image_delete ||= "0"
end
def image_delete=(value)
#image_delete = value
end
private
def destroy_image?
self.images.clear if #image_delete == "1"
end
end
class Work::Image < Asset
has_attached_file :attachment, :styles => {:small => "200x150>", :large => "400x300>"},
:url => "/uploads/works/:id/:style/:basename.:extension",
:path => ":rails_root/public/uploads/works/:id/:style/:basename.:extension"
end
I think the problem is that delete all images
self.images.clear if #image_delete == "1"
but I don't understand how to fix it. I hope in your help.

You should use the :allow_destroy options of accepts_nested_attributes_for instead.
And in your form something like this:
<% #work.images.each do |image| %>
<%= f.fields_for :images, image do |image_fields| %>
<%= image_tag image.url(:small) %>
<%= image_fields.check_box :_destroy %>
<% end %>
<% end %>

Related

Paper clip image showing up in wrong place

Hey i have a rails app that i am uploading images with paperclip....
So i have a comic_review scaffold that i upload images of comic covers and i also have a news scaffold where i post news and images.....
When i edit news/1/edit and upload a picture the comics_review/1 picture becomes the same as the news one and vice a versa.
I checked the links in the views to make sure that i is correct and they seem to be ok...
heres my view
home.html.erb
<h2 style="color: black; font-size: 30px;"><%= #comic_review1.title %></h2>
<p><%= #comic_review1.content %></p>
<%= link_to 'Read More...', comic_review_path(#comic_review1) %>
<%= image_tag #comic_review1.photo, class: "homepage_comics" %>
news/show.html
<%= #news.author %>
<%= #news.date %>
<%= image_tag #news.photo, class: 'pull-left', style: 'margin-right: 10px;' %>
heres my controller
static_pages_controller.rb
class StaticPagesController < ApplicationController
def home
#user = current_user
#article = Article.first
#comic_review1 = ComicReview.find(1)
#comic_review2 = ComicReview.find(2)
#comic_review3 = ComicReview.find(3)
#comic_review4 = ComicReview.find(4)
end
def comics
#comic_review1 = ComicReview.find(1)
#comic_review2 = ComicReview.find(2)
#comic_review3 = ComicReview.find(3)
#comic_review4 = ComicReview.find(4)
end
def batnews
#article = Article.first
#news_all = News.all
end
end
heres my model
comic_review.rb
class ComicReview < ActiveRecord::Base
attr_accessible :content, :credits, :review, :title, :photo, :comicreview
has_attached_file :photo, :styles => { :small => '400x400' },
:storage => :s3,
:s3_credentials => "#{Rails.root}/config/s3.yml",
:path => ":attachment/activities/:id/:style.:extension",
:bucket => 'goddam_batman_pics'
has_many :comments, as: :commentable, dependent: :destroy
end
news.rb
class News < ActiveRecord::Base
attr_accessible :title, :author, :date, :content, :photo
has_attached_file :photo, :styles => { :small => '400x400' },
:storage => :s3,
:s3_credentials => "#{Rails.root}/config/s3.yml",
:path => ":attachment/activities/:id/:style.:extension",
:bucket => 'goddam_batman_pics'
end
controllers are your basic controllers that gets generated by the scaffold
so whenever i update a photo for news/1 the photo for comic_reviews/1 gets the same photo as the news one
any help would be appreciated thank you
I'm pretty sure the problem is that you're giving the "photo" the same name in both models. Try naming one comic_photo and the other news_photo, or alternately, explore Polymorphic Associations.
Dated Railscast link, but gives you the idea - http://railscasts.com/episodes/154-polymorphic-association
PS - Bonus points for figuring out how to load four ComicReviews in one query rather than four in those controllers.
ok so what i had to do was in my model i changed the path from
:path => ":attachment/activities/:id/:style.:extension",
to
:path => "/image/:id/:filename",
and it seems to be working

accepts_nested_attributes_for with has_many polymorphic

I use paperclip to upload multi-file attached to studentcourseassignment,but i fail.
model
class StudentCourseAssignment < ActiveRecord::Base
attr_accessible :score, :comment, :finish_status,:attachments
accepts_nested_attributes_for :attachments
belongs_to :assignment
belongs_to :user
has_many :attachments ,:as => :attachmentable,:dependent => :destroy
end
class Attachment < ActiveRecord::Base
attr_accessible :user_upload
belongs_to :attachmentable , :polymorphic => true
has_attached_file :user_upload
end
controller
**new**
#sca = StudentCourseAssignment.new
#sca.attachments.build
#sca.attachments.build
**create**
#sca = StudentCourseAssignment.new(params[:student_course_assignment])
#assignment = Assignment.find(params[:assignment_id])
#sca.user = current_user
#sca.assignment = #assignment
if #sca.save
flash[:alert] = "success"
redirect_to course_years_path
else
flash[:alert] = "fail"
redirect_to course_years_path
end
** view**
<%= form_for #sca, :url => assignment_student_course_assignments_path(#assignment),
:html => { :id => 'student-assignment-form', :multipart => true } do |f| %>
file:
<%= f.fields_for :attachments do |a_f| %>
<%= a_f.file_field :user_upload %>
<%= submit_tag "create" %>
<% end%>
<% end %>
wrong
No association found for name `attachments'. Has it been defined yet?
if remove accepts_nested_attributes_for :attachments,it's still wrong
Attachment(#70201401779680) expected, got Array(#70201383294620)
hope your help!thx!
Change
from:
attr_accessible :score, :comment, :finish_status,:attachments
to:
attr_accessible :score, :comment, :finish_status,:attachments_attributes
I realize this is an old question, but fwiw I think you'll need to move
accepts_nested_attributes_for :attachments
to appear after
has_many :attachments, :as => :attachmentable,:dependent => :destroy
I hit this in a project once myself; pretty sure it boils down to accepts_nested_attributes_for expecting the relation to already be declared before its invoked.

rails 3 polymorphic association with paperclip and multiple models

I want to make polymorphic associations with paperclip, and allow my user to have one avatar and multiple images.
Attachment model:
class Attachment < ActiveRecord::Base
belongs_to :attachable, :polymorphic => true
end
class Avatar < Attachment
has_attached_file :image, :styles => { :thumb => "150x150>", :view => "260x180>" },
end
class Image < Attachment
has_attached_file :image, :styles => { :thumb => "150x150>", :view => "260x180>" },
end
User Model:
has_one :avatar, :as => :attachable, :class_name => 'Attachment', :conditions => {:type => 'avatar'}
accepts_nested_attributes_for :avatar
User Controller:
def edit
#user.build_avatar
end
User View form:
<%= form_for #user, :html => { :multipart => true } do |f| %>
<%= f.fields_for :avatar do |asset| %>
<% if asset.object.new_record? %>
<%= asset.file_field :image %>
<% end %>
<% end %>
when I attempt to save the changes I get the error => unknown attribute: avatar
if I remove the :class_name => 'attachment' in the has_one association I get the error =>
uninitialized constant User::Avatar
I need to also attach avatars to blog posts, so I need the association to be polymorphic (or atleast i think so)
I am stumped and any help would be greatly appreciated.
I do have a project in the works that is successfully using Paperclip and polymorphic associations. Let me show you what I have, and maybe you can apply it to your project:
class Song < ActiveRecord::Base
...
has_one :artwork, :as => :artable, :dependent => :destroy
accepts_nested_attributes_for :artwork
...
end
class Album < ActiveRecord::Base
...
has_one :artwork, :as => :artable, :dependent => :destroy
accepts_nested_attributes_for :artwork
...
end
class Artwork < ActiveRecord::Base
belongs_to :artable, :polymorphic => true
attr_accessible :artwork_content_type, :artwork_file_name, :artwork_file_size, :artwork
# Paperclip
has_attached_file :artwork,
:styles => {
:small => "100",
:full => "400"
}
validates_attachment_content_type :artwork, :content_type => 'image/jpeg'
end
the songs form and the albums form include this as a partial:
<div class="field">
<%= f.fields_for :artwork do |artwork_fields| %>
<%= artwork_fields.label :artwork %><br />
<%= artwork_fields.file_field :artwork %>
<% end %>
don't forget to include :html => { :multipart => true } with the form
artworks_controller.rb
class ArtworksController < ApplicationController
def create
#artwork = Artwork.new(params[:artwork])
if #artwork.save
redirect_to #artwork.artable, notice: 'Artwork was successfully created.'
else
redirect_to #artwork.artable, notice: 'An error ocurred.'
end
end
end
and finally, an excerpt from songs_controller.rb:
def new
#song = Song.new
#song.build_artwork
end
I'm not sure you really need to be polymorphic. How about this approach, which uses has_many :through? In plain English, the user has one avatar which has multiple images, and through this association you can call User.images to get the collection of images associated with the avatar.
http://guides.rubyonrails.org/association_basics.html
class User < ActiveRecord::Base
has_one :avatar
has_many :images, :through => :avatar
end
class Avatar < ActiveRecord::Base
belongs_to :user
has_many :images
end
class Image < ActiveRecord::Base
belongs_to :avatar
has_attached_file :image, :styles => { :thumb => "150x150>", :view => "260x180>" },
end
Having said all of this, I am left to wonder why you need to go through all this anyway. Why not just do
class User < ActiveRecord::Base
has_many :avatars
end
which would give you as many images (avatars) as you want.

Rails Nested Attribute Retrieval in Controller

Here's the structure of my code. I have a video attached with each cresponse and as far as I can tell I have been successful in uploading it. The problem comes when I need to convert it after the structure is saved. I wish to access the newly updated nested attribute (see lesson_controller) but am not sure how to go about doing so.
Many thanks!
Pier.
lesson.rb
class Lesson < ActiveRecord::Base
has_one :user
has_many :comments, :dependent => :destroy
has_many :cresponses, :dependent => :destroy
acts_as_commentable
accepts_nested_attributes_for :comments, :reject_if => lambda { |a| a[:body].blank? }, :allow_destroy => true
accepts_nested_attributes_for :cresponses
and here's cresponse.rb
class Cresponse < ActiveRecord::Base
belongs_to :lesson
attr_accessible :media, :accepted, :description, :user_id
# NOTE: Comments belong to a user
belongs_to :user, :polymorphic => true
# Paperclip
require 'paperclip'
has_attached_file :media,
:url => "/system/:lesson_id/:class/:basename.:extension",
:path => ":rails_root/public/system/:lesson_id/:class/:basename.:extension"
Here's my HTML view
<% #cresponse = #lesson.cresponses.build %>
<%= form_for #lesson, :html => { :multipart => true } do |f| %>
<td class="list_discussion" colspan="2">
<div class="field">
<%= f.fields_for :cresponses, #cresponse, :url => #cresponse, :html => { :multipart => true } do |builder| %>
Upload : <%= builder.file_field :media %><br />
Description : <%= builder.text_field :description %>
<%= builder.hidden_field :user_id , :value => current_user.id %>
<% end %>
</div>
</td>
and here's lesson_controller.rb - update
def update
#lesson = Lesson.find(params[:id])
respond_to do |format|
if #lesson.update_attributes(params[:lesson])
**if #lesson.cresponses.** <-- not sure how to find the cresponse that I need to convert
puts("Gotta convert this")
end
Think I should answer my own question ..
Basically for lesson_controller.rb
params[:lesson][:cresponses_attributes].values.each do |cr|
#cresponse_user_id = cr[:user_id]
#cresponse_description = cr[:description]
if cr[:media]
.... and so on

Carrierwave image upload in nested form still creating record even no file is specified

I have a Carrierwave image upload in a nested simple_form which works (sort of) unless the user does not specify a file, in which case a blank Picture object is created unless there was a previously existing one. Not quite sure how to make it so that if the user doesn't specify a "new" image to upload, the old one isn't deleted and/or a blank record without a file is created.
One (maybe odd) thing I am doing is always sending the logged in #user to the user#edit action, then building a #user.picture if it doesn't exist. I am thinking this is where my bad design is.
# user.rb
class User < ActiveRecord::Base
[...]
has_one :picture, :dependent => :destroy
accepts_nested_attributes_for :picture
[...]
end
# picture.rb
class Picture < ActiveRecord::Base
attr_accessible :image, :remove_image
belongs_to :user
mount_uploader :image, ImageUploader
end
# users_controller.rb
def edit
if #user.picture.nil?
#user.build_picture
end
end
#_form.html.erb
<%= simple_form_for #user, :html => {:multipart => true} do |f| %>
<%= render "shared/error_messages", :target => #user %>
<h2>Picture</h2>
<%= f.simple_fields_for :picture do |pic| %>
<% if #user.picture.image? %>
<%= image_tag #user.picture.image_url(:thumb).to_s %>
<%= pic.input :remove_image, :label => "Remove", :as => :boolean %>
<% end %>
<%= pic.input :image, :as => :file, :label => "Picture" %>
<%= pic.input :image_cache, :as => :hidden %>
<% end %>
<br/>
#rest of form here
<% end %>
I think I had the same issue which I solved by adding a reject_if option to the accepts_nested_attribute. So in your example, you could do something like
class User < ActiveRecord::Base
[...]
has_one :picture, :dependent => :destroy
accepts_nested_attributes_for :picture,
:reject_if => lambda { |p| p.image.blank? }
[...]
end
When you use build_* it sets the foreign key on the object. ( similar to saying Picture.new(:user_id => id) )
Try This
# users_controller.rb
def edit
if #user.picture.nil?
#user.picture = Picture.new
end
end
Today I had the same problem, I solved this like:
accepts_nested_attributes_for :photos,
:reject_if => :all_blank

Resources