In my app there are products and images, which I manage via a simple admin panel. I can successfully add images to products if there are no images, but when I upload at least one (I can do it via edit or initial create), I can't do further uploads or delete existing images. I simply don't understand why the initial create or update works, but the further don't, if there is a mistake with my routes or in my controller, it would've been there at the first picture addition, wouldn't it?
This is the mistake when I try to add a new picture to an existing product with existing pictures via editing (if there are no initial pictures the update performs correctly) :
ActionController::RoutingError (No route matches [POST] "/admin/products/20"):
actionpack (4.2.4) lib/action_dispatch/middleware/debug_exceptions.rb:21:in `call'
web-console (2.2.1) lib/web_console/middleware.rb:39:in `call'
actionpack (4.2.4) lib/action_dispatch/middleware/show_exceptions.rb:30:in `call'
My form:
=form_for([:admin, @product]) do |f|
%p
...a lot of simple fields, that are working correctly
.box
%h3 Options
=f.fields_for :options do |builder|
=render 'option_fields', f: builder
%br
=link_to_add_fields 'Add an option', f, :options
=f.fields_for :image, Image.new, html: { multipart: true, id: "fileupload" } do |op|
= op.label 'Load product pictures'
= op.file_field :image, multiple: true, id: 'fileupload', name: "product[images_attributes][][image]", class: 'form-control'
-if @product.images.any?
.box
%h6 Delete existing pictures
%p
=f.fields_for :images do |builder|
=image_tag builder.object.image, width: 120
=builder.label :_destroy, 'Delete picture'
=builder.check_box :_destroy
%br
%hr.short.alt
=f.submit 'Save', id: 'submit-data', class: 'btn btn-success'
=link_to 'Back', admin_path, class: 'btn btn-info'
This is my Products-Admin-controller
class Admin::ProductsController < AdminController
before_action :find_product, only: [:edit, :destroy, :update]
def index
@products = Product.all
end
def edit
end
def new
@product = Product.new
option = @product.options.build
@product.servizations.build
end
def create
@product = Product.new(product_params)
if @product.save
redirect_to admin_products_path
flash[:success] = "Created"
else
render action: :new
end
end
def update
if @product.update!(product_params)
redirect_to edit_admin_product_path(@product)
flash[:success] = "Updated"
else
render action: :edit
end
end
def destroy
if @product.destroy
redirect_to admin_products_path
flash[:info] = 'Deleted
end
end
private
def product_params
params.require(:product).permit(:title, :description, :advertising_text,
:fancy_quote, :hot, :hotpic, :product_size_ids, :material,
{ volume_ids: [] }, { color_ids: [] }, { addservice_ids: [] }, :category_id, :subcategory_id,
options_attributes: [:size, :weight, :price, :material, :product_id, :id],
images_attributes: [ :image, :product_id, :id ],
servizations_attributes: [:id, :product_id, :addservice_id, :coefficient]
)
end
def find_product
@product = Product.find(params[:id])
end
end
My product model:
class Product < ActiveRecord::Base
validates :title, :description, :advertising_text, presence: true
validates :category_id, :subcategory_id, presence: true
mount_uploader :hotpic, HotpicUploader
belongs_to :category
belongs_to :subcategory
has_many :options
has_many :images, dependent: :destroy
has_many :hot_pics
has_many :line_items
has_many :voluminazations
has_many :volumes, through: :voluminazations
has_many :colorizations
has_many :colors, through: :colorizations
has_many :accompanships
has_many :accompanies, through: :accompanships
has_many :servizations
has_many :addservices, through: :servizations
accepts_nested_attributes_for :options
accepts_nested_attributes_for :images
accepts_nested_attributes_for :hot_pics
accepts_nested_attributes_for :servizations
before_destroy :ensure_not_referenced_by_any_line_item
def initialized_servizations # this is the key method
[].tap do |o|
Addservice.all.each do |addservice|
if c = servizations.find { |c| c.addservice_id == addservice.id }
o << c.tap { |c| c.enable ||= true }
else
o << Servization.new(addservice_id: addservice.id)
end
end
end
end
private
# Ensure there are no line items referencing this product
def ensure_not_referenced_by_any_line_item
if line_items.empty?
return true
else
errors.add(:base, 'Line Items present')
return false
end
end
end
My routes if they matter:
resources :products do
resources :servizations
resources :colors
resources :options do
resources :option_pics
end
end
namespace :admin do
get '', to: 'dashboard#index', as: '/'
resources :products do
resources :images
end
resources :categories
resources :subcategories
resources :volumes
resources :members
resources :addservices
resources :settings
resources :deliveries
end
Update. As requested, my rake routes:
admin_product_images GET /admin/products/:product_id/images(.:format) admin/images#index
POST /admin/products/:product_id/images(.:format) admin/images#create
new_admin_product_image GET /admin/products/:product_id/images/new(.:format) admin/images#new
edit_admin_product_image GET /admin/products/:product_id/images/:id/edit(.:format) admin/images#edit
admin_product_image GET /admin/products/:product_id/images/:id(.:format) admin/images#show
PATCH /admin/products/:product_id/images/:id(.:format) admin/images#update
PUT /admin/products/:product_id/images/:id(.:format) admin/images#update
DELETE /admin/products/:product_id/images/:id(.:format) admin/images#destroy
admin_products GET /admin/products(.:format) admin/products#index
POST /admin/products(.:format) admin/products#create
new_admin_product GET /admin/products/new(.:format) admin/products#new
edit_admin_product GET /admin/products/:id/edit(.:format) admin/products#edit
admin_product GET /admin/products/:id(.:format) admin/products#show
PATCH /admin/products/:id(.:format) admin/products#update
PUT /admin/products/:id(.:format) admin/products#update
DELETE /admin/products/:id(.:format) admin/products#destroy