ruby-on-railsrubyparametersshrine

Unpermitted parameter: :photos_attributes


I want to use shrine gem in nested form, But happened

Unpermitted parameter: :photos_attributes

How to solve it? I tried some ways, that

def blog_form_params
  params.require(:blog_form).permit(:title , :content ).merge!(user_id: current_user.id , :photos_attributes =>[:image, :id ,:destroy ])
end

and

def blog_form_params
 params.require(:blog_form).permit(:title , :content ).merge!(user_id: current_user.id , photos_attributes: {:image, :id ,:destroy })
end

So on, but I can't solve it what is a matter of this error? Please tell me how to solve it

Strong Parameters

 def blog_form_params
   params.require(:blog_form).permit(:title , :content ).merge!(user_id: 
   current_user.id , 
   photos_attributes: [:image, :id ,:destroy ])
  end

BlogForm.rb

 class BlogForm


 include ActiveModel::Model

 attr_accessor :title, :content, :user_id , :photos

 def blog_builder

@user = User.find(user_id) 

@blogs = @user.blogs.create(title: title , content: content )

return @blogs

end


concerning :PhotosBuilder do

  attr_reader :photos_attributes


  def photos
    @blogs = blog_builder
    @photos ||= @blogs.photos.new
 end

 def photos_attributes=(attributes)
   @blogs = blog_builder
@photos ||= @blogs.photos.new(attributes)
 end

end

def build_association


  @user.photos << @photos if @photos != nil

end


 def save
   return false if invalid?
   blog_builder
   @blogs.save
   @photos.save if @photos != nil
   build_association

 end
end

Send parameters

{"authenticity_token"=>"qDssddHt4EhfFWN33SPMk2F5fcvPToh143hrwilw0p98HK2RMEwdKDF7QsGYiSQ7AQHN02lpdBaCbSAed80Swg==",
  "blog_form"=>{"title"=>"", "content"=>"sample", "photos_attributes"=> 
  {"image"=>#<ActionDispatch::Http::UploadedFile:0x00007f92408f07a8 @ 
   tempfile=#<Tempfile:/tmp/RackMultipart20200406-4102-1x3utj1.png>, 
    @original_filename="p8-1.png", @content_type="image/png", 
    @headers="Content-Disposition: form-data; 
    name=\"blog_form[photos_attributes][image]\"; filename=\"p8- 
    1.png\"\r\nContent-Type: image/png\r\n">}}, "commit"=>"create", 
    "user_id"=>"2"}  

blog.rb

class Blog < ApplicationRecord
 belongs_to :user
 has_many :photos
 validates :title ,presence: true
 validates :content ,presence: true

end

photo.rb

 class Photo < ApplicationRecord
  belongs_to :blog
  belongs_to :user
  include ImageUploader[:image]

end

uploader.rb

   class ImageUploader < Shrine
    end

shrine.rb

   require "shrine/storage/file_system"


Shrine.storages = {
   cache: Shrine::Storage::FileSystem.new("public", prefix: "uploads/cache"), # temporary
   store: Shrine::Storage::FileSystem.new("public", prefix: "uploads/store"), # permanent
 }


Shrine.plugin :activerecord
Shrine.plugin :cached_attachment_data

blogs_controller

  def new

    @blog_form = BlogForm.new

 end

    def create

       @blog_form = BlogForm.new(blog_form_params)
       if @blog_form.save
       redirect_to user_blogs_path
       else
         #False action
       end

     end

 def blog_form_params
    params.require(:blog_form).permit(:title , :content, photos_attributes: 
     [:image] ).merge!(user_id: current_user.id)
  end

I could solve this problem, Instead, I can't merge user_id Then happened ActiveRecord::RecordNotFound (Couldn't find User without an ID):

  def blog_builder


@user = User.find(user_id)#Here is a new problem

@blogs = @user.blogs.create(title: title , content: content )

return @blogs

end

Maybe I could send params

(byebug) blog_form_params                                                                                               
 <ActionController::Parameters {"title"=>"", "content"=>"sample", 
 "photos_attributes"=><ActionController::Parameters {"image"=># 
  <ActionDispatch::Http::UploadedFile:0x00007f9240bc77b0 @tempfile=# 
  <Tempfile:/tmp/RackMultipart20200406-4102-rc9eo6.png>, 
  @original_filename="p8-1.png", @content_type="image/png", 
  @headers="Content-Disposition: form-data; 
  name=\"blog_form[photos_attributes][image]\"; filename=\"p8- 
  1.png\"\r\nContent-Type: image/png\r\n">} permitted: true>, "user_id"=>2} 
  permitted: true>  

So error is attriubute to form object

I uploaded blog_form.rb

def blog_builder


@user = User.find(params[:user_id])#previously User.find(user_id)

@blogs = @user.blogs.create(title: title , content: content )

return @blogs

end

Doesn't work it, I got to (byebug) params[:user_id] *** NameError Exception: undefined local variable or method `params' for #

nil

I changed user_id instead of params[:user_id] So that

(byebug)  @blog_form.user_id=params[:user_id]                                                                           
 NoMethodError Exception: undefined method `user_id=' for nil:NilClass                                                                                                                                                                   
 nil   

Create

def create

@blog_form = BlogForm.new(blog_form_params)
@blog_form.user_id=params[:user_id]
if @blog_form.save

Blog_form

def blog_builder


@user = User.find(user_id)

@blogs = @user.blogs.create(title: title , content: content )

return @blogs

end

blog_form_params

  (byebug) blog_form_params                                                                                               
  <ActionController::Parameters {"title"=>"title", "content"=>"sample", 
  "photos_attributes"=><ActionController::Parameters {"image"=># 
  <ActionDispatch::Http::UploadedFile:0x00007f80f5209680 @tempfile=# 
  <Tempfile:/tmp/RackMultipart20200407-10555-iewcks.png>, 
   @original_filename="p8-1.png", @content_type="image/png", 
   @headers="Content-Disposition: form-data; 
   name=\"blog_form[photos_attributes][image]\"; filename=\"p8- 
   1.png\"\r\nContent-Type: image/png\r\n">} permitted: true>, "user_id"=>2} 
   permitted: true>

Somwhow I could sent an user_id, I appreciate Fernand, Amit Patel, I used hidden_field in view filed instead of merge method


Solution

  • that is because you put the photos_attributes in the merge portion instead as blog_form attribute

    how about this:

    params.require(:blog_form).permit(:title , :content, :photos_attributes =>[:image, :id, :destroy] )
    

    then update blogs_controller:

    def create
      @blog_form = BlogForm.new(blog_form_params)
      @blog_form.user_id=params[:user_id]
      ...
    

    then in BlogForm.rb:

    def blog_builder
      @user = User.find(user_id)
      ...