Rails 4 Paperclip Images not uploading/showing - ruby-on-rails

I used paperclip gem to implement multiple image upload in my app.
My models are as follows
class ProductImage < ActiveRecord::Base
belongs_to :product
has_attached_file :image ,:styles => {
:thumb => ['100x100#', :jpg, :quality => 70],
:preview => ['480x480#', :jpg, :quality => 70],
:large => ['600>', :jpg, :quality => 70],
:retina => ['1200>', :jpg, :quality => 30]
},:path => ':rails_root/public/system/:id.:extension',
:convert_options => {
:thumb => '-set colorspace sRGB -strip',
:preview => '-set colorspace sRGB -strip',
:large => '-set colorspace sRGB -strip',
:retina => '-set colorspace sRGB -strip -sharpen 0x0.5'
},
:url => "/assets/books/:id/:style/:basename.:extension",
:path => ":rails_root/public/assets/books/:id/:style/:basename.:extension"
validates_attachment_presence :image
validates_attachment_size :image , :less_than => 10.megabytes
validates_attachment_content_type :image , :content_type => ['image/jpeg','image/jpg','image/png']
do_not_validate_attachment_file_type :image
end
class Product < ActiveRecord::Base
belongs_to :user
belongs_to :category
has_many :comments , dependent: :destroy
has_many :product_images, :dependent => :destroy
accepts_nested_attributes_for :product_images, :reject_if => lambda { |t| t['product_image'].nil? }
end
product_controller.rb
class ProductsController < ApplicationController
def new
#product = current_user.products.new
3.times {#product.product_images.build}
end
def create
#product = current_user.products.new
3.times { #product.product_images.build }
respond_to do |format|
if #product.save
format.html { redirect_to #product, notice: 'Product was successfully created.' }
format.json { render :show, status: :created, location: #product }
else
format.html { render :new }
format.json { render json: #product.errors, status: :unprocessable_entity }
end
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_product
#product = Product.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def product_params
params.require(:product).permit(:name, :price, :description, :reason, :user_id,:status,:category_id,product_images_attributes: [:image])
end
def correct_user
#product = current_user.products.find_by(id: params[:id])
redirect_to root_url if #product.nil?
end
end
_form.html.erb
<%= form_for #product, url: products_path, :html => {:multipart => true,:class => " form-horizontal center"} do |f| %>
<%= f.fields_for :product_images do |builder| %>
<p>
<%= builder.label :image, "Image File" %>
<%= builder.file_field :image %>
</p>
<% end %>
<div class="actions">
<%= f.submit "Submit", class: "btn btn-default btn-primary" %>
</div><br/>
<% end %>
show.html.erb
<% #products.each do |product| %>
<% product.product_images.each do |picture| %>
<%= picture.image.url %>
<% end %>
When i submit files page is not redirected to homepage.i cant even see errors.Can somebody explain me whats the problem in the code

The one thing i notice is in the product controller create action:
#product = current_user.products.new
should be:
#product = current_user.products.build(product_params)
you should always pass in product_params when creating new object in the create action.

Related

Missing file field in Nested Attributes

I'm using paperclip in nested attributes and I'm not sure what I'm missing. The view on the form is missing the file upload option.
Form
<%= form_with(model: news, local: true, html: { multipart: true } ) do |form| %>
<%= form.fields_for :images do |img| %>
<%= img.file_field :img, multiple: true %>
<% end%>
<% end %>
Models
class News < ApplicationRecord
has_many :images, dependent: :destroy
accepts_nested_attributes_for :images, allow_destroy: true
end
class Image < ApplicationRecord
belongs_to :news
has_attached_file :img, :styles => { :show => "600x600>" }, size: { less_than: 2.megabytes }
validates_attachment_content_type :img, :content_type => ["image/jpg", "image/jpeg", "image/gif", "image/png"]
end
Controller
class NewsController < ApplicationController
def new
#news = News.new
#news.images.build
end
def create
#news = News.new(news_params)
respond_to do |format|
if #news.save
format.html { redirect_to #news, notice: 'News was successfully created.' }
format.json { render :show, status: :created, location: #news }
else
format.html { render :new }
format.json { render json: #news.errors, status: :unprocessable_entity }
end
end
end
private
def set_news
#news = News.find(params[:id])
end
def news_params
params.require(:news).permit(:title, :description, :category, images_attributes: [:id, :img, :news_id, :_destroy])
end
end
If I change :images to :image in the form the field appears, but then gives an error on submission:
Unpermitted parameter: :image
In your case, you need to explicitly pass a record_object to the fields_for
<%= form.fields_for :images, #news.images.build do |img| %>
<%= img.file_field :img, multiple: true %>
<% end%>
Also in order to send multiple values for img, it should be an array in the permitted params. You should change the news_params to below
def news_params
params.require(:news).permit(:title, :description, :category, images_attributes: [:id, :news_id, :_destroy, img: []])
end

Ruby on Rails paperclip multiple upload with nested attributes

I was wondering if someone can help me with file uploading!
I'm trying to upload multiple images using paperclip and having nested attributes.
models
class Trip < ActiveRecord::Base
has_many :trip_images, :dependent => :destroy
end
class TripImage < ActiveRecord::Base
belongs_to :trip
has_attached_file :photo, :styles => { :large => "800x800>", :medium => "500x500>", :thumb => "150x150#" }, :default_url => "/images/:style/missing.png"
validates_attachment_content_type :photo, content_type: /\Aimage\/.*\Z/
end
controller
def create
#trip = Trip.new(trip_params)
respond_to do |format|
if #trip.save
format.html { redirect_to #trip, notice: 'Trip was successfully created.' }
format.json { render :show, status: :created, location: #trip }
else
format.html { render :new }
format.json { render json: #trip.errors, status: :unprocessable_entity }
end
end
end
def trip_params
params.require(:trip).permit(
:user_id,
trip_images_attributes: [:id, :photo])
end
view
<%= simple_form_for #trip, html: { multipart: true } do |f| %>
<%= f.simple_fields_for :trip_images do |p| %>
<%= p.file_field :photo, as: :file, multiple: true %>
<% end%>
<%= f.button :submit %>
<% end %>
How do I save multiple images in my trip image database? When I submit the form, nothing gets saved into the database.
Add :trip_id to trip_images_attributes:
def trip_params
params.require(:trip).permit(
:user_id,
trip_images_attributes: [:trip_id, :id, :photo]) # :_destroy
end
Also you can add :_destroy if you plan to be able to remove photos.
What you also missed is to add accepts_nested_attributes_for :trip_images to Trip model.
Change your form to something like this:
= f.simple_fields_for :trip_images do |tp|
= render 'trip_photos_fields', f: photo
.links
%br= link_to_add_association 'Add another photo', f
And _trip_photos_fields.html.haml partial:
- unless f.object.new_record?
%br= link_to_remove_association "Delete photo", f
= link_to image_tag(f.object.photo.url(:medium)), f.object.photo.url, target: '_blank'
- if f.object.new_record?
= f.file_field :photo, as: :file

Paperclip Issue - can't update and create

CONTROLLER
CREATE
def create
set_cache_buster
#court_agency = CourtAgency.new(court_agency_params)
#court_agency.created_by = current_user
#court_agency.updated_by = current_user
binding.pry
respond_to do |format|
if #court_agency.save
flash[:success] = 'Court was successfully created.'
format.html do
redirect_to court_agencies_path
end
format.js { render :js => "window.location = '#{court_agencies_path}'" }
else
format.json { render json: #court_agency.errors, status: :unprocessable_entity }
end
end
end
UPDATE
def update
set_cache_buster
#court_agency = CourtAgency.find(params[:id])
#court_agency.updated_by = current_user
respond_to do |format|
if #court_agency.update_attributes(court_agency_params)
flash[:success] = 'Court was successfully updated.'
format.html do
redirect_to court_agencies_path
end
format.js { render :js => "window.location = '#{court_agencies_path}'" }
else
format.json { render json: #court_agency.errors, status: :unprocessable_entity }
end
end
end
STRONG PARAMETER
def court_agency_params
params.require(:court_agency).permit(
:type,
:subtype,
:division,
:associate_justice,
:presiding_justice,
:map,
:landmark_image,
]
) if params[:court_agency]
end
MY VIEW
= form_for(#court_agency, remote: true, html: { :multipart => true, class: 'form-horizontal ajax-form', style: 'margin-bottom: 0;', 'data-model-name' => 'court_agency'}) do |f|
.form-group
= f.label :landmark_image, 'Landmark', class: 'control-label'
%br/
= f.file_field :landmark_image, class: 'btn btn-warning'
- if #court_agency.map.present?
= image_tag #court_agency.map.url(:small), class: 'img-responsive img-thumbnail'
.form-group
= f.label :map, 'Map', class: 'control-label'
%br/
= f.file_field :map, class: 'btn btn-warning'
- if #court_agency.map.present?
= image_tag #court_agency.map.url(:small), class: 'img-responsive img-thumbnail'
MODEL
#Paperclip
has_attached_file :map,
:styles => { :large => "900x900>", :medium => "300x300>", :thumb => "196x196>", :small => '50x50>' },
:default_url => ActionController::Base.helpers.asset_path('missing.png'),
:url => "/assets/court_agencies/:id/:style/:basename.:extension",
:path => ":rails_root/public/assets/court_agencies/:id/:style/:basename.:extension"
validates_attachment_content_type :map, :content_type => /\Aimage\/.*\Z/
has_attached_file :landmark_image,
:styles => { :large => "900x900>", :medium => "300x300>", :thumb => "196x196>", :small => '50x50>' },
:default_url => ActionController::Base.helpers.asset_path('missing.png'),
:url => "/assets/court_agencies/:id/:style/:basename.:extension",
:path => ":rails_root/public/assets/court_agencies/:id/:style/:basename.:extension"
validates_attachment_content_type :landmark_image, :content_type => /\Aimage\/.*\Z/
Ok here's the problem:
When I create without file upload, it works. But when I attach file, params not working and it leaves blank. So when I binding.pry:
[1] pry(#<CourtAgenciesController>)> params
=> {"action"=>"create", "controller"=>"court_agencies"}
Params is missing.
When I update without file upload, it works. But when I attach file, the error is:
Started POST "/court_agencies/53" for 127.0.0.1 at 2015-04-08 16:03:21 +0800
ActionController::RoutingError (No route matches [POST] "/court_agencies/53"):
or just like
Routing Error
No route matches [POST] "/court_agencies/53"
on browser.
I have remotipart installed.
Also Paperclip.
Please help. Need it badly.
UPDATE:
ROUTES:
#COURT AGENCY
resources :court_agencies do
member do
get 'list'
put 'update_uin'
end
collection do
get 'get_court_agency_list'
get 'court_agency_list'
get 'add'
get 'get_uin'
end
end
This issue is about remote: true. How is it possible to create/update submitting via ajax with file upload?
do you have defined attr_accessible in your model...i didnt see that in your model
attr_accessible: :type,:subtype,:division,:associate_justice,:presiding_justice,:map,:landmark_image,

Why is adding multiple images to a gallery object not working at all

I am creating a gallery where you can upload multiple images via form.
The form is nested inside another form and when that is submitted it should create the gallery with the attached images inside it. When I check the output I get this which means its not submitting the correct images to the gallery object at all:
Parameters: {
"utf8"=>"✓",
"authenticity_token"=>"BJhkDx7rCRMIlXQ6T9FskXZe7+fdYxj0qm+VnCaC51w=",
"book"=>{
"jacket_cover" =>#<ActionDispatch::Http::UploadedFile:0x000001025d3128
#tempfile=#<File:/var/folders/mf/srx7jt8s2rdg0mn5hr98cvz80000gn/T/RackMultipart20140918-47766-1g9kyas>, #original_filename="559a7a477253d58f891f8e852162dfac.jpg", #content_type="image/jpeg", #headers="Content-Disposition: form-data; name=\"book[jacket_cover]\"; filename=\"559a7a477253d58f891f8e852162dfac.jpg\"\r\nContent-Type: image/jpeg\r\n">,
"title"=>"zd szw wrwr",
"synopsis"=>"<p>cfdcrgcgrere</p>\r\n",
"body"=>"<p>rccgregrrgerereg</p>\r\n",
"age"=>"19",
"publisher"=>"Dove books",
"author_attributes"=>{
"name"=>"zsdxfrrwg",
"biography"=>"<p>exffwfwefewewf</p>\r\n"},
"gallery_attributes"=>{
"images_attributes"=>{
"0"=>{
"file"=>[#<ActionDispatch::Http::UploadedFile:0x000001025d20e8 #tempfile=#<File:/var/folders/mf/srx7jt8s2rdg0mn5hr98cvz80000gn/T/RackMultipart20140918-47766-tk1rdb>, #original_filename="23ebb202a3655c6d0947251cce8625b6.jpg", #content_type="image/jpeg", #headers="Content-Disposition: form-data; name=\"book[gallery_attributes][images_attributes][0][file][]\"; filename=\"23ebb202a3655c6d0947251cce8625b6.jpg\"\r\nContent-Type: image/jpeg\r\n">, #<ActionDispatch::Http::UploadedFile:0x000001025d1ff8 #tempfile=#<File:/var/folders/mf/srx7jt8s2rdg0mn5hr98cvz80000gn/T/RackMultipart20140918-47766-j3ji7c>, #original_filename="559a7a477253d58f891f8e852162dfac.jpg", #content_type="image/jpeg", #headers="Content-Disposition: form-data; name=\"book[gallery_attributes][images_attributes][0][file][]\"; filename=\"559a7a477253d58f891f8e852162dfac.jpg\"\r\nContent-Type: image/jpeg\r\n">]
}
}
}
}, "commit"=>"Create Book"
}
The books_controller handles the submission of the gallery with the images in it:
class BooksController < ApplicationController
before_action :set_book, only: [:show, :edit, :update, :destroy]
before_filter :authenticate_user!, only: [:new, :edit, :update, :destroy]
# GET /books
# GET /books.json
def index
#books = Book.order('created_at DESC').all
end
# GET /books/1
# GET /books/1.json
def show
# #book = Book.find(params[:id])
#book = Book.friendly.find(params[:id])
#gallery = #book.gallery
end
# GET /books/new
def new
#book = Book.new
#book.build_author
#gallery = #book.build_gallery
#gallery.images.build
end
# GET /books/1/edit
def edit
end
# POST /books
# POST /books.json
def create
#raise params.inspect
#book = Book.new(book_params)
#binding.pry
respond_to do |format|
if #book.save
format.html { redirect_to #book, notice: 'Book was successfully created.' }
format.json { render action: 'show', status: :created, location: #book }
else
format.html { render action: 'new' }
format.json { render json: #book.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /books/1
# PATCH/PUT /books/1.json
def update
respond_to do |format|
if #book.update(book_params)
format.html { redirect_to #book, notice: 'Book was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #book.errors, status: :unprocessable_entity }
end
end
end
# DELETE /books/1
# DELETE /books/1.json
def destroy
#book.destroy
respond_to do |format|
format.html { redirect_to books_url }
format.json { head :no_content }
end
end
# Get authors
# def reviews
# #book = Book.friendly.find(params[:id])
# #reviews = #movie.reviews
# respond_to do |format|
# format.html { render 'reviews/index' } # index.html.erb
# format.json { render json: #movies }
# end
# end
private
# Use callbacks to share common setup or constraints between actions.
def set_book
# #book = Book.find(params[:id])
#book = Book.friendly.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def book_params
params.require(:book).permit(:title, :synopsis, :body, :age, :publisher, :jacket_cover, author_attributes: [:name,:biography], gallery_attributes: [:name, :book_id ] )
end
end
book.rb
class Book < ActiveRecord::Base
has_attached_file :jacket_cover, :styles => { :medium => "300x300>", :thumb => "100x100>" }, :default_url => "/images/:style/missing.png"
validates_attachment_content_type :jacket_cover, :content_type => /\Aimage\/.*\Z/
validates :jacket_cover, :title, :slug, :synopsis, :body, :age, :publisher, presence: true
validates_uniqueness_of :title
extend FriendlyId
friendly_id :title, use: [:slugged, :finders]
belongs_to :author
has_one :gallery
has_many :stories
accepts_nested_attributes_for :author
accepts_nested_attributes_for :gallery
scope :available, ->{ where(available: true) }
scope :unavailable, ->{ where(available: [nil, false]) }
end
image.rb
class Image < ActiveRecord::Base
belongs_to :gallery
has_attached_file :file, :styles => { :medium => "300x300>", :thumb => "100x100>" }, :default_url => "/images/:style/missing.png"
validates_attachment_content_type :file, :content_type => /\Aimage\/.*\Z/
end
gallery.rb
class Gallery < ActiveRecord::Base
belongs_to :books
has_many :images
accepts_nested_attributes_for :books
accepts_nested_attributes_for :images, :allow_destroy => true
end
galleries_controller.rb
class GalleriesController < ApplicationController
before_action :set_gallery, only: [:show, :edit, :update, :destroy]
def index
#galleries = Gallery.all
end
def show
#gallery = Gallery.find(params[:id])
#images = #gallery.images
end
def new
#gallery = Gallery.new
##gallery.images.build
# #images = #gallery.build_images
# #gallery.images.build
end
def edit
#gallery.images.build
end
def create
#gallery = Gallery.new(gallery_params)
#image = Image.create()
##gallery.images.build
respond_to do |format|
if #gallery.save
format.html { redirect_to #gallery, notice: 'Gallery was successfully created.' }
format.json { render action: 'show', status: :created, location: #gallery }
else
format.html { render action: 'new' }
format.json { render json: #gallery.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if #gallery.update(gallery_params)
format.html { redirect_to #gallery, notice: 'Gallery was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #gallery.errors, status: :unprocessable_entity }
end
end
end
def destroy
#gallery.destroy
respond_to do |format|
format.html { redirect_to galleries_url }
format.json { head :no_content }
end
end
private
def set_gallery
#gallery = Gallery.find(params[:id])
end
def gallery_params
params.require(:gallery).permit(:name, :book_id, :image)
#params.require(:gallery).permit(:name, :book_id, :images[], images_attributes: [:id, :file []])
#params.require(:gallery).permit(:name, :book_id, :images[images_attributes: [:file]])
# params.require(:gallery).permit(:name, :book_id, images_attributes: [:id, :image[:file]])
end
end
Added form in here that submits the gallery of images:
<%= simple_form_for(#book, :html => { :multipart => true } ) do |f| %>
<%= f.error_notification %>
<div class="inputs">
<div id="image" class="field">
<h3>Add the book image here</h3>
<div class="single-file">
<div class="file_upload">
<%= f.file_field :jacket_cover %>
</div>
</div>
</div>
<div id="title" class="field">
<h3>Add the title</h3>
<%= f.input :title %>
</div>
<div id="synopsis" class="field">
<h3>Add the book synopsis</h3>
<%= f.input :synopsis, :as => :ckeditor, :label => false, :input_html => { :ckeditor => { :toolbar => 'Full', :height => 400 } } %>
</div>
<div id="body" class="field">
<h3>Add the book body summary here</h3>
<%= f.input :body, :as => :ckeditor, :label => false, :input_html => { :ckeditor => { :toolbar => 'Full', :height => 400 } } %>
</div>
<div id="age" class="field">
<h3>Add the book age group</h3>
<%= f.input :age, collection: [['3-7', '3-7'],['7-11', '7-11'],['11-14', '11-14']], prompt: "Select age range" %>
</div>
<div id="publisher" class="field">
<h3>Who published the book</h3>
<%= f.input :publisher %>
</div>
<div id="school" class="field">
<h3>Schools reading this book (add the name and full address of the school)</h3>
<%= f.simple_fields_for :schools, :wrapper => 'inline' do |builder| %>
<%= render 'school_fields', :f => builder %>
<%= link_to_add_association 'add school', f, :schools, :render_options => {:wrapper => 'inline' }, :class => 'fa fa-plus' %>
<% end %>
</div>
</div>
<%#= f.select( :author_id, Author.all.map {|u| [u.name,u.id]}, {:include_blank => false, prompt: "No Author"} ) %>
<div id="author-inputs">
<h3>Add author</h3>
<%#= link_to 'New Author', new_author_path, :remote => true, :id => "new_author_link" %>
<%= f.simple_fields_for :author, :wrapper => 'inline' do |builder| %>
<%= render 'author_fields', :f => builder %>
<% end %>
</div>
<%= f.simple_fields_for :gallery do |builder| %>
<%= render 'galleries/form', :f => builder %>
<% end %>
<div class="actions">
<%= f.button :submit %>
</div>
<% end %>
When I check in the db console I cannot see any images inside the gallery when I search Gallery.all
I have created a gist file with all the necessary info in it.
Can anyone shed any light into this for me at all?
The main problem is with your parent form and model relationship.
In your book model you should have belongs_to :gallery instead of has_one :gallery. Also check your database. books Table should have gallery_id. As a database concept belongs_to should have parent table id. So model should be :
class Book < ActiveRecord::Base
has_attached_file :jacket_cover, :styles => { :medium => "300x300>", :thumb => "100x100>" }, :default_url => "/images/:style/missing.png"
validates_attachment_content_type :jacket_cover, :content_type => /\Aimage\/.*\Z/
validates :jacket_cover, :title, :slug, :synopsis, :body, :age, :publisher, presence: true
validates_uniqueness_of :title
extend FriendlyId
friendly_id :title, use: [:slugged, :finders]
belongs_to :author
belongs_to :gallery
has_many :stories
accepts_nested_attributes_for :author
accepts_nested_attributes_for :gallery
scope :available, ->{ where(available: true) }
scope :unavailable, ->{ where(available: [nil, false]) }
end
and your gallery model should look like :
class Gallery < ActiveRecord::Base
has_many :books
has_many :images
accepts_nested_attributes_for :books
accepts_nested_attributes_for :images, :allow_destroy => true
end
Your parent model in form should be gallery model instead of book. And also make required changes in your gallery controller.

mutiple upload with rails and paperclip

I am following this tutorial here to use multiple uploads with paperclip.
However when I add the files I get the flash notice confirming the gallery was added succesfully but there are no images uploaded. I am sure its the implementation in my controller.
gallery_controller.rb
def update
#gallery = Gallery.friendly.find params[:id]
respond_to do |format|
if #gallery.save
if params[:exhibition_images_attributes]
params[:exhibition_images_attributes].each { |image|
#gallery.exhibition_images.create(image: image)
}
end
format.html { redirect_to #gallery, notice: 'Gallery was successfully updated.' }
format.json { render :show, status: :ok, location: #gallery }
else
format.html { render :edit }
format.json { render json: #gallery.errors, status: :unprocessable_entity }
end
end
end
def edit
#gallery = Gallery.friendly.find params[:id]
#image = #gallery.exhibition_images.new
end
private
def gallery_params
params.require(:gallery).permit(:title, exhibition_images_attributes: [:image])
end
upload form
<%= bootstrap_form_for(#gallery, :html => {:multipart => true}, layout: :horizontal, label_col: "col-sm-2", control_col: "col-sm-10") do |f| %>
<%= f.text_field :title %>
<%= f.fields_for :exhibition_images do |f| %>
<%= f.file_field "image[]", type: :file, multiple: true %>
<% end %>
<%= f.submit "Create/Update", class: "btn btn-primary" %>
<% end %>
gallery.rb
class Gallery < ActiveRecord::Base
extend FriendlyId
friendly_id :title, use: :slugged
belongs_to :guide
has_many :exhibition_images, :autosave => true
accepts_nested_attributes_for :exhibition_images
end
exhibition_image.rb
class ExhibitionImage < ActiveRecord::Base
belongs_to :gallery, :autosave => true
has_attached_file :image, styles: { small: "100x100", guide: "500x500" }
validates_attachment_content_type :image, :content_type => ["image/jpg", "image/jpeg", "image/png", "image/gif"]
end

Resources