Issue
I am using rails as a backend and angular as a frontend. I want to save images to rails backend. I decided to use the paperclip gem. Here is the error below.
↳ app/controllers/products_controller.rb:49:in `set_product’
Unpermitted parameters: :id, :created_at, :updated_at,
:image_file_name, :image_content_type, :image_file_size,
:image_updated_at
Here is some model for angular.
export class Product {
public image:File;
...//the rest of the variables
}
Here is where I set the value of the products image.
public fileSelected(event) {
this.product.image=event.target.files[0];
}
Then I use the httpclient angular functions to send it. That all is working so I wont show it unless requested. Only with an image does this fail.
On the rails side. Here is the paperclip migration
class AddAttachmentImageToProducts < ActiveRecord::Migration[6.0]
def self.up
change_table :products do |t|
t.attachment :image
end
end
def self.down
remove_attachment :products, :image
end
end
My model
class Product < ActiveRecord::Base
has_attached_file :image, styles: { medium: "300x300>", thumb: "100x100>" }, default_url: "/images/:style/missing.png"
validates_attachment :image, presence: true
do_not_validate_attachment_file_type :image
end
My controller
class ProductsController < ApplicationController
before_action :set_product, only: [:show, :update, :destroy]
# GET /products
def index
@products = Product.all
render json: @products.to_json
end
# GET /products/1
def show
render json: @products.image
end
# POST /products
def create
@products = Product.new(product_params)
if @products.save
render json: @products, status: :created, location: @products
else
render json: @products.errors, status: :unprocessable_entity
end
end
# PATCH/PUT /products/1
def update
if @products.update(product_params)
render json: @products
else
render json: @products.errors, status: :unprocessable_entity
end
end
# DELETE /products/1
def destroy
@products.destroy
end
private
# Use callbacks to share common setup or constraints between actions.
def set_product
@products = Product.find(params[:id])
end
# Only allow a trusted parameter "white list" through.
def product_params
params.require(:product).permit(:name, :description, :image)
end
end
Solution
If you are using Rails API, then you should use paperclip adapters to save the image. You have to send base64 file front end.
def update
@products.name = params[:product][:name]
@products.description = params[:product][:description]
image_base = params[:product][:image] ###base64 text of your image came from front-end
image = Paperclip.io_adapters.for(image_base)
image.original_filename = "image" ###Name of the file, you can take it from parameters / you can assign it statically
@products.image = image
if @products.save
##Do your stuff
else
render json: @products.errors, status: :unprocessable_entity
end
end
In case if you get any exceptions after adding above code in your controller, create a config/initializers/paperclip.rb file and place the following code in that initializer
Paperclip::DataUriAdapter.register
require 'paperclip/media_type_spoof_detector'
module Paperclip
class MediaTypeSpoofDetector
def spoofed?
false
end
end
end