Reputation: 808
I need to upload more than one image to products in a app I'm building.
The Images are uploaded via ActiveAdmin
with paperclip
There is no problem uploading one image, but multiple images is not working.
I've tried to use the jquery-fileupload-rails
gem and it is supposed to wire into active admin
, but with out a luck.
I have also searched the web for this and checked out many posts on Stack Overflow, but I haven't found a solution yet.
Here is the product model product.rb
class Product < ActiveRecord::Base
acts_as_list :scope => [:category, :label]
belongs_to :category
belongs_to :label
has_many :product_items, :dependent => :destroy
validates :title, :description, presence: true
validates :price_usd, :price_eur, numericality: {greater_than_or_equal_to: 0.01}
validates :title, uniqueness: true
has_attached_file :image, styles: { medium: "500x500#", thumb: "100x100#" }
validates_attachment_content_type :image, content_type: /\Aimage\/.*\z/
end
THIRD UPDATE
Ok I added this images_attributes:
snipped below to the products_controller.rb
in the end of the def product_params
def product_params
params.require(:product).permit(:title, :description,...., images_attributes: [:image , :id , :_destroy])
end
And to the admin/product.rb
I added
f.has_many :images , heading: false, allow_destroy: true do |ff|
ff.input :image, required: true, as: :file
end
Now I can select images via active admin, but it don't get saved to the database.
ANOTHER UPDATE
Here is the app/views/pages/index.html.erb
In that snippet located on the index page the latest upload in each category is shown. See how the app loops through products and shows the corresponding image to each product. Now I'm getting error from this line <%= image_tag product.image.url(:medium), class: "img-responsive" %>
in the index file.
<div class="container-fluid">
<% @products.each_slice(3) do |products_group| %>
<div class="row">
<% products_group.each do |category, products| %>
<% products.each_with_index do |product, index| %>
<% if index == 0 %>
<div class="col-lg-4 col-sm-6 col-xs-12 center-block " >
<%= link_to category_path (category), { :method => 'GET' } do %>
<%= image_tag product.image.url(:medium), class: "img-responsive" %>
<% end %>
<div class="caption">
<p class="category-name" ><%= product.category.name %></p>
</div>
<% end %>
<% end %>
</div>
<% end %>
</div>
<% end %>
</div>
UPDATE
here is the `products_controller.rb`
class ProductsController < ApplicationController
before_action :set_product, only: [:show, :edit, :update, :destroy]
def show
offset = rand(100)
@products_rand = Product.where(category_id:
@product.category_id).order("RANDOM()").limit(6)
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(:title, :description, :price_usd, :price_eur, :image, :category_id, :stock_quantity, :label_id, :query, :slug)
end
end
And this is the Active admin product model admin/product.rb
ActiveAdmin.register Product do
config.sort_order = 'position_asc' # assumes you are using 'position' for your acts_as_list column
config.paginate = true # optional; drag-and-drop across pages is not supported
sortable # creates the controller action which handles the sorting
permit_params :title, :slug, :description, :stock_quantity, :image, :price_usd, :price_eur, :category_id, :label_id, images_attributes: [:image , :id , :_destroy]
index do
sortable_handle_column # inserts a drag handle
column :title
column :slug
column :category
column :label
column :created_at
column :stock_quantity
column :price_eur, :sortable => :price_eur do |product|
number_to_currency(product.price_eur, :unit => "€ " , :precision => 0)
end
column :price_euro, :sortable => :price_usd do |product|
number_to_currency(product.price_usd, :unit => "$ " , :precision => 0)
end
actions
end
form multipart: true do |f|
f.inputs "Product Details" do
f.input :title
f.input :slug
f.input :description, as: :ckeditor, input_html: { ckeditor: { toolbar: 'Full' } }
f.input :stock_quantity
f.input :image, required: false
f.input :price_usd
f.input :price_isl
f.input :category
f.input :label
end
f.actions
end
end
And finally here is the product view, `app/views/products/show.html.erb``
<div class="container">
<div class="row product_top text-center">
<div class="col-xs-12 col-sm-6 center-block">
<div class="product_description">
<h3 class="title"><%= @product.title %></h3>
<p class="label-product"><%= @product.label.name %></p>
<p class="description">Description</p>
<p class="product-description"><%= @product.description.html_safe %></p>
<% if @product.stock_quantity <= 0 %>
<p> Out of stock </p>
<% end %>
</div>
<div class="col-xs-12">
<p class="product-price"> Price:</p> <%= number_to_currency(@product.price_usd, :unit => "€ " , :precision => 0) %> | <%= number_to_currency(@product.price_isl.to_i, :unit => "IKR " , :precision => 0) %>
</div>
<%# if @product.stock_quantity >= 1 %>
<div class="row text-center add-cart-wrapper">
<% if @product.stock_quantity >= 1 %>
<%= link_to 'Add to Cart', product_product_items_path(@product), :method => :post, class: 'add-to-cart'%>
<% end %>
</div>
</div>
<div class="col-xs-12 col-sm-6 center-block" >
<%= image_tag @product.image.url(:medium), class: "img-responsive center-block" %>
</div>
</div>
<div class="row product-teaser">
<h4 class="text-center teaser-text"> similar products to <%= @product.title %> : </h4>
<% @products_rand.each do |product| %>
<div class="col-sm-2 col-xs-3 center-block product-thumbs-product-view" >
<%= link_to product_path (product) do %>
<%= image_tag product.image.url, :size => "100%x100%", class: "img-responsive center-block" %>
<% end %>
<h5 class="text-center"><%= link_to product.title, product, class: "text-center" %></h5>
</div>
<% end %>
</div>
</div>
Upvotes: 0
Views: 466
Reputation: 13521
That model, as you have it, can only hold one file upload in its image
attribute. You need to add a has_many
association to your product so that it can have many files.
i.e. create an Image model that will hold the attachment and be associated to the product:
rails g model Image product_id:integer image_file_name:string image_file_size:integer image_content_type:string
rake db:migrate
Then associate the product to it:
class Product < ActiveRecord::Base
has_many :images
# ... the rest of your code...
end
And move the attached file declaration to your Image model:
class Image < ActiveRecord::Base
belongs_to :product
has_attached_file :image, styles: { medium: "500x500#", thumb: "100x100#" }
validates_attachment_content_type :image, content_type: /\Aimage\/.*\z/
end
Now you have a way of associating many images with one product:
product = Product.new
product.images.build image: File.open('some/image/for/example.jpg', ?r)
product.save
product.images.first.image # the Paperclip::Attachment object
I can only take you this far since you didn't post any controller, view code, or active_admin setup but, you just need to read rails or active_admin documentation on nested resources so that you can figure out how to write a nested form that lets you create these images for your Product.
Update: If by "taking this answer further" you mean "write the code for you" Then, no. There is enough information here and in the active_admin documentation on nested resources for you to figure it out. I can however, provide clarifications if any of this is confusing.
Upvotes: 3